Edited at

【Android】SearchViewを使って検索画面を実装する

More than 3 years have passed since last update.


1. はじめに

Qittaroというアプリを作っているときに検索画面の実装が必要になりました。

よくある検索ワードを入力してもらって、その結果を表示するという流れのアプリです。

最初はFragmentの中にEditTextを入れて、setOnEditorActionListener()でEnterを押されたら...という流れの処理を作りました。

こんな感じっす。

EditText editText = (EditText)this.findViewById(R.id.edit_text);

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
// ここに処理
}
}
});

みたいになやつです。

しかし、検索ワードの入力が検索結果一覧のところに一緒にあるのも変だなと思っていたら、TwitterのアプリでActionBarのところに検索ワードを入力できるのを発見して探してみました。

そして無事実装できたので、この実装を紹介したいと思います。


2. SearchViewの実装

探し当てたのはandroid.widget.SearchViewというものでした。

SearchView | Android Developers

特に難しいことはなかったので、実装から入力ワードの摘出までを紹介します。


2.1. SupportLibrary

いきなりですが、android.widget.SearchViewAPI Level 11以上となっています。

Qittaroはandroid version 2.3以上を対象にしているので、このままでは使えませんが、SupportLibraryがあったのでそちらを使いました。

しかし、実装はそこまで変わらないので、どちらでも簡単に導入できます。


2.2. ソースコード

ということで、ソースコードを御覧ください。


SearchFragment.java

import android.os.Bundle;

import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.Menu;
import android.view.ViewGroup;

public class SearchFragment extends Fragment {

private static final String TAG = SearchFragment.class.getSimpleName();
private final SearchFragment self = this;

private SearchView searchView;
private String searchWord;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// FragmentでMenuを表示する為に必要
this.setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Menuの設定
inflater.inflate(R.menu.search, menu);

// app:actionViewClass="android.support.v7.widget.SearchView"のItemの取得
MenuItem menuItem = menu.findItem(R.id.search_menu_search_view);

/**
* API level 11以上の場合はこっちを使う
*
* this.searchView = (SearchView)menuItem.getActionView();
*/

// ActionViewの取得
this.searchView = (SearchView) MenuItemCompat.getActionView(menuItem);

// 虫眼鏡アイコンを最初表示するかの設定
this.searchView.setIconifiedByDefault(true);

// Submitボタンを表示するかどうか
this.searchView.setSubmitButtonEnabled(false);

if (!this.searchWord.equals("")) {
// TextView.setTextみたいなもの
this.searchView.setQuery(this.searchWord, false);
} else {
String queryHint = self.getResources().getString(R.string.search_menu_query_hint_text);
// placeholderみたいなもの
this.searchView.setQueryHint(queryHint);
}
this.searchView.setOnQueryTextListener(self.onQueryTextListener);
}

private SearchView.OnQueryTextListener onQueryTextListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String searchWord) {
// SubmitボタンorEnterKeyを押されたら呼び出されるメソッド
return self.setSearchWord(searchWord);
}

@Override
public boolean onQueryTextChange(String newText) {
// 入力される度に呼び出される
return false;
}
};

private boolean setSearchWord(String searchWord) {
ActionBar actionBar = ((ActionBarActivity)this.getActivity()).getSupportActionBar();
actionBar.setTitle(searchWord);
actionBar.setDisplayShowTitleEnabled(true);
if (searchWord != null && !searchWord.equals("")) {
// searchWordがあることを確認
this.searchWord = searchWord;
}
// 虫眼鏡アイコンを隠す
this.searchView.setIconified(false);
// SearchViewを隠す
this.searchView.onActionViewCollapsed();
// Focusを外す
this.searchView.clearFocus();
return false;
}
}



search.xml

<!-- res/menu/search.xml -->

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>

<item
android:id="@+id/search_menu_search_view"
android:orderInCategory="100"
android:title="@string/search_menu_search_text"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"
/>

</menu>



2.3. スクリーンショット

こんな感じになります。

スマホの場合

ScreenShot01


タブレットの場合

ScreenShot02


2.4. 注意点

特にカスタマイズをしていないので、最小限の設定になります。

今回はFragmentで検索ワードを取得したかったので、FragmentMenuを実装しました。

Activityは特になにもしていません。

ワードにさらに検索オプションみたいなのをつけようとすると苦労すると思います。

その場合は素直にEditText + Buttonみたいな実装をする方がよろしいかと思います。


3. 終わりに

これ見つけた時はなんかすっごい嬉しかったです。

SDKでこういうのを準備していてくれたんだなって思いまして...。

使えるものは使っておこう精神で良いかと思っています。

これで素敵な検索画面を実装してくださいませ。