Впровадження SearchView на панелі дій


83

Мені потрібно створити SearchViewз мого arrayList<String>і показати пропозиції у розкривному списку те саме

введіть тут опис зображення

Я шукаю підручники, які покроково пояснюють, як побудувати 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>`

Але я не знаю, як встановити параметри масиву рядків. Я намагався отримати результат в іншій діяльності, але не працював.


6
Ви повинні розмістити все, що спробували, якомога детальніше. Конкретні питання із зразком коду, як правило, отримують швидші, змістовніші відповіді.
Коллін Флінн

Відповіді:


128

Потрібен був час, щоб зібрати рішення для цього, але виявили, що це найпростіший спосіб змусити його працювати так, як ви описуєте. Можуть бути кращі способи зробити це, але оскільки ви не опублікували свій код діяльності, мені доведеться імпровізувати і припустити, що у вас є такий список на початку вашої діяльності:

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);

            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 / searchchable.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ваш проект.


3
Привіт, але один сумнів, я сподіваюся, ви допоможете мені в цьому. Якщо я наберу одну літеру на фільтрі, хоча у мене є результати фільтру, нічого не відображатиметься, якщо більше одного. тоді лише воно відображається. чому?
Наруто

Привіт, можливо, перевірте свої стилі на що-небудь пов’язане з EditText або AutoCompleteTextView, оскільки ви можете встановити кількість символів за замовчуванням, які потрібно ввести, перш ніж воно покаже автозаповнення. Насправді я думаю, що за замовчуванням 2 символи, тому, можливо, вам потрібно буде додати це до стилів, щоб змінити його.
tpbapp

Привіт, під час розробки я натрапив на ще одне питання searchview. якщо я відображаю більше елементів у випадаючому списку, наприклад: 3 текстові перегляди, тоді розмір елемента збільшується, тому елементи пошуку протікають на клавіатурі, якщо я прокручую, як i.stack.imgur.com/d7t3A.png . Це трапляється, якщо я збільшую розмір тексту або додаю більше переглядів у елементі. Це поведінка за замовчуванням?
Наруто

Знову привіт, ні, цього не повинно відбуватися. Схоже, у вас є багато коду вже в проекті, який заважає AutoCompleteTextView у SearchView, або, можливо, щось не так із програмним забезпеченням клавіатури та додатком чи плагіном, що спричиняє таку поведінку. Поведінка за замовчуванням має бути приблизно такою: stackoverflow.com/questions/22116237/ ... за винятком того, що ця людина насправді запитує, як зробити так, щоб вона не була схована за клавіатурою.
tpbapp

3
@tpbapp Я це вже зрозумів. Причина, чому список пропозицій не з’являється, полягає у тому, що у вашому коді ви search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));два рази викликали методи onCreateOptionsMenu()and loadHistory(). Тож я роблю глобальну змінну SearchView та SearchManager і викликаю лише getSearchableInfo()один раз onCreateOptionsMenu(). І мій список пропозицій зараз працює ідеально. Я пропоную вам переглянути ваш код.
Hafizh Herdi

53

Якщо хтось інший має nullptr для змінної searchview, я виявив, що налаштування елемента трохи відрізняється:

старий:

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"

Для отримання додаткової інформації, він оновлюється документація знаходиться тут .


3
Дякую. Тільки те, чого мені не вистачало. :-)
Мортен Е. Расмуссен

Дякую, що це було просто та корисно.
Мухаммед

1
app:actionViewClass="androidx.appcompat.widget.SearchView"для androidx
HendraWD

4

SearchDialog або SearchWidget?

Що стосується реалізації функціональності пошуку , офіційною документацією розробника Android пропонується два підходи .
Ви можете використовувати SearchDialog або SearchWidget .
Я збираюся пояснити реалізацію функціональності пошуку за допомогою SearchWidget.

Як це зробити за допомогою віджета Search?

Я пояснити функціонал пошуку в RecyclerView за допомогою SearchWidget. Це досить просто.

Просто виконайте ці 5 простих кроків

1) Додайте в меню пункт searchView

Ви можете додати, SearchViewможна додати, як actionViewу меню за допомогою

додаток: 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, слухач тощо

Вам слід ініціалізувати SearchView у onCreateOptionsMenu(Menu menu)методі.

  @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 має два абстрактні методи

  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();
}

Відповідне посилання:

Повний робочий код на SearchView з базою даних SQLite у цій програмі Music


1

Для 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();
    }
    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.