web-dev-qa-db-ja.com

アクションバーにSearchViewを実装する

arrayList<String>からSearchViewを作成し、これと同じドロップダウンリストに提案を表示する必要があります

enter image description here

アクションバーでSearchViewを作成する方法を段階的に説明するチュートリアルを探しています。

私は ドキュメント を読み、Googleの例に従っていますが、私にとっては役に立ちませんでした。

検索を作成しました

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:id="@+id/action_search"
          Android:title="Search"
          Android:icon="@Android:drawable/ic_menu_search"
          Android:showAsAction="always"
          Android:actionViewClass="Android.widget.SearchView" />
</menu>`

しかし、文字列の配列のパラメーターを設定する方法がわかりません。別のアクティビティで結果を取得しようとしましたが、機能しませんでした。

79
Matteo

これに対する解決策をまとめるのにしばらく時間がかかりましたが、これがあなたが説明する方法で動作させる最も簡単な方法であることがわかりました。これを行うためのより良い方法がありますが、アクティビティコードを投稿していないため、アクティビティの開始時に次のようなリストが用意されていると仮定する必要があります。

private List<String> items = db.getItems();

ExampleActivity.Java

private List<String> items;

private Menu menu;

@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.example, menu);

    this.menu = menu;

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

        SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

        SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();

        search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));

        search.setOnQueryTextListener(new OnQueryTextListener() { 

            @Override 
            public boolean onQueryTextChange(String query) {

                loadHistory(query);

                return true; 

            } 

        });

    }

    return true;

}

// History
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void loadHistory(String query) {

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

        // Cursor
        String[] columns = new String[] { "_id", "text" };
        Object[] temp = new Object[] { 0, "default" };

        MatrixCursor cursor = new MatrixCursor(columns);

        for(int i = 0; i < items.size(); i++) {

            temp[0] = i;
            temp[1] = items.get(i);replaced s with i as s not used anywhere.

            cursor.addRow(temp);

        }

        // SearchView
        SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

        final SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();

        search.setSuggestionsAdapter(new ExampleAdapter(this, cursor, items));

    }

}

ここで、CursorAdapterから拡張されたアダプターを作成する必要があります。

ExampleAdapter.Java

public class ExampleAdapter extends CursorAdapter {

    private List<String> items;

    private TextView text;

    public ExampleAdapter(Context context, Cursor cursor, List<String> items) {

        super(context, cursor, false);

        this.items = items;

    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        text.setText(items.get(cursor.getPosition()));

    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = inflater.inflate(R.layout.item, parent, false);

        text = (TextView) view.findViewById(R.id.text);

        return view;

    }

}

これを行うより良い方法は、リストデータがデータベースからのものである場合、データベース関数によって返されるCursorを直接ExampleAdapterに渡し、関連する列セレクターを使用して、アダプターで参照されるTextViewの列テキストを表示することです。

注:CursorAdapterをインポートするときは、Androidサポートバージョンをインポートしないで、代わりに標準のAndroid.widget.CursorAdapterをインポートしてください。

アダプターには、カスタムレイアウトも必要です。

res/layout/item.xml

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <TextView
        Android:id="@+id/item"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

</RelativeLayout>

追加のテキストビューまたは画像ビューをレイアウトに追加し、アダプターにデータを入力することにより、リストアイテムをカスタマイズできるようになりました。

これですべてのはずですが、まだこれを行っていない場合は、SearchViewメニュー項目が必要です。

res/menu/example.xml

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <item
        Android:id="@+id/search"
        Android:title="@string/search"
        Android:showAsAction="ifRoom"
        Android:actionViewClass="Android.widget.SearchView" />

</menu>

次に、検索可能な構成を作成します。

res/xml/searchable.xml

<searchable xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:label="@string/search"
    Android:hint="@string/search" >
</searchable>

最後に、これをマニフェストファイルの関連するアクティビティタグ内に追加します。

AndroidManifest.xml

<intent-filter>
    <action Android:name="Android.intent.action.SEARCH" />
</intent-filter>

<meta-data
    Android:name="Android.app.default_searchable"
    Android:value="com.example.ExampleActivity" />
<meta-data
    Android:name="Android.app.searchable"
    Android:resource="@xml/searchable" />

注:例で使用されている@string/search文字列はvalues/strings.xmlで定義する必要があります。また、プロジェクトのcom.exampleへの参照を更新することを忘れないでください。

123
tpbapp

他の誰かがsearchview変数にnullptrを設定している場合、アイテムのセットアップが少し異なることがわかりました。

古い:

Android:showAsAction="ifRoom"
Android:actionViewClass="Android.widget.SearchView"

新しい:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"

android x以前:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="Android.support.v7.widget.SearchView"

詳細については、更新されたドキュメントが こちらにあります です。

46
Grease

SearchDialogまたはSearchWidget?

検索機能の実装に関しては、Android開発者向け公式ドキュメントによる 2つの推奨されるアプローチ があります。
SearchDialogまたはSearchWidgetのいずれかを使用できます。
SearchWidgetを使用した検索機能の実装について説明します。

検索ウィジェットでそれを行う方法は?

SearchWidgetを使用してRecyclerViewの検索機能を説明します。とても簡単です。

これらの5つの簡単な手順に従ってください

1)メニューにsearchViewアイテムを追加します

SearchViewを追加するには、メニューでactionViewとして追加できます。

app:useActionClass = "Android.support.v7.widget.SearchView".

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
   xmlns:app="http://schemas.Android.com/apk/res-auto"
   xmlns:tools="http://schemas.Android.com/tools"
   tools:context="rohksin.com.searchviewdemo.MainActivity">
   <item
       Android:id="@+id/searchBar"
       app:showAsAction="always"
       app:actionViewClass="Android.support.v7.widget.SearchView"
   />
</menu>

2)SerchView Hintテキスト、リスナーなどを設定します

onCreateOptionsMenu(Menu menu)メソッドでSearchViewを初期化する必要があります。

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
     // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        MenuItem searchItem = menu.findItem(R.id.searchBar);

        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setQueryHint("Search People");
        searchView.setOnQueryTextListener(this);
        searchView.setIconified(false);

        return true;
   }

3)アクティビティにSearchView.OnQueryTextListenerを実装します

OnQueryTextListenerには2つの抽象メソッドがあります

  1. onQueryTextSubmit(String query)
  2. onQueryTextChange(String newText

アクティビティスケルトンは次のようになります

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

     public boolean onQueryTextSubmit(String query)

     public boolean onQueryTextChange(String newText) 

}

4)SearchView.OnQueryTextListenerを実装する

このような抽象メソッドの実装を提供できます

public boolean onQueryTextSubmit(String query) {

    // This method can be used when a query is submitted eg. creating search history using SQLite DB

    Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onQueryTextChange(String newText) {

    adapter.filter(newText);
    return true;
}

5)ご使用のRecyclerViewアダプターにフィルターメソッドを記述します。

最も重要な部分。独自のロジックを作成して、検索を実行できます。
これは私のものです。このスニペットは、SearchViewに入力されたテキストを含む名前のリストを示しています

public void filter(String queryText)
{
    list.clear();

    if(queryText.isEmpty())
    {
       list.addAll(copyList);
    }
    else
    {

       for(String name: copyList)
       {
           if(name.toLowerCase().contains(queryText.toLowerCase()))
           {
              list.add(name);
           }
       }

    }

   notifyDataSetChanged();
}

関連リンク:

これでSQLiteデータベースを使用したSearchViewの完全な動作コード Music App

3
Rohit Singh

Searchviewにはこれらのコードを使用します

  1. XMLの場合

    <Android.support.v7.widget.SearchView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:id="@+id/searchView">
    
    </Android.support.v7.widget.SearchView>
    

  2. フラグメントまたはアクティビティ内

    package com.example.user.salaryin;
    
    import Android.app.ProgressDialog;
    import Android.os.Bundle;
    import Android.support.v4.app.Fragment;
    import Android.support.v4.view.MenuItemCompat;
    import Android.support.v7.widget.GridLayoutManager;
    import Android.support.v7.widget.LinearLayoutManager;
    import Android.support.v7.widget.RecyclerView;
    import Android.support.v7.widget.SearchView;
    import Android.view.LayoutInflater;
    import Android.view.Menu;
    import Android.view.MenuInflater;
    import Android.view.MenuItem;
    import Android.view.View;
    import Android.view.ViewGroup;
    import Android.widget.Toast;
    import com.example.user.salaryin.Adapter.BusinessModuleAdapter;
    import com.example.user.salaryin.Network.ApiClient;
    import com.example.user.salaryin.POJO.ProductDetailPojo;
    import com.example.user.salaryin.Service.ServiceAPI;
    import Java.util.ArrayList;
    import Java.util.List;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    
    
    public class OneFragment extends Fragment implements SearchView.OnQueryTextListener {
    
    RecyclerView recyclerView;
    RecyclerView.LayoutManager layoutManager;
    ArrayList<ProductDetailPojo> arrayList;
    BusinessModuleAdapter adapter;
    private ProgressDialog pDialog;
    GridLayoutManager gridLayoutManager;
    SearchView searchView;
    
    public OneFragment() {
        // Required empty public constructor
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        View rootView = inflater.inflate(R.layout.one_fragment,container,false);
    
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Please wait...");
    
    
        searchView=(SearchView)rootView.findViewById(R.id.searchView);
        searchView.setQueryHint("Search BY Brand");
        searchView.setOnQueryTextListener(this);
    
        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        layoutManager = new LinearLayoutManager(this.getActivity());
        recyclerView.setLayoutManager(layoutManager);
        gridLayoutManager = new GridLayoutManager(this.getActivity().getApplicationContext(), 2);
        recyclerView.setLayoutManager(gridLayoutManager);
        recyclerView.setHasFixedSize(true);
        getImageData();
    
    
        // Inflate the layout for this fragment
        //return inflater.inflate(R.layout.one_fragment, container, false);
        return rootView;
    }
    
    
    private void getImageData() {
        pDialog.show();
        ServiceAPI service = ApiClient.getRetrofit().create(ServiceAPI.class);
        Call<List<ProductDetailPojo>> call = service.getBusinessImage();
    
        call.enqueue(new Callback<List<ProductDetailPojo>>() {
            @Override
            public void onResponse(Call<List<ProductDetailPojo>> call, Response<List<ProductDetailPojo>> response) {
                if (response.isSuccessful()) {
                    arrayList = (ArrayList<ProductDetailPojo>) response.body();
                    adapter = new BusinessModuleAdapter(arrayList, getActivity());
                    recyclerView.setAdapter(adapter);
                    pDialog.dismiss();
                } else if (response.code() == 401) {
                    pDialog.dismiss();
                    Toast.makeText(getActivity(), "Data is not found", Toast.LENGTH_SHORT).show();
                }
    
            }
    
            @Override
            public void onFailure(Call<List<ProductDetailPojo>> call, Throwable t) {
                Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
                pDialog.dismiss();
    
            }
        });
    }
    
       /* @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        getActivity().getMenuInflater().inflate(R.menu.menu_search, menu);
        MenuItem menuItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
        searchView.setQueryHint("Search Product");
        searchView.setOnQueryTextListener(this);
    }*/
    
    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }
    
    @Override
    public boolean onQueryTextChange(String newText) {
        newText = newText.toLowerCase();
        ArrayList<ProductDetailPojo> newList = new ArrayList<>();
        for (ProductDetailPojo productDetailPojo : arrayList) {
            String name = productDetailPojo.getDetails().toLowerCase();
    
            if (name.contains(newText) )
                newList.add(productDetailPojo);
            }
        adapter.setFilter(newList);
        return true;
       }
    }
    
  3. アダプタークラス

     public void setFilter(List<ProductDetailPojo> newList){
        arrayList=new ArrayList<>();
        arrayList.addAll(newList);
        notifyDataSetChanged();
    }
    
1
Neeraj Gupta