작업 표시 줄에서 SearchView 구현


82

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
시도한 모든 것을 가능한 한 자세하게 게시해야합니다. 샘플 코드가있는 특정 질문은 더 빠르고 의미있는 답변을 얻는 경향이 있습니다.
Collin Flynn 2014

답변:


127

이에 대한 해결책을 모으는 데 시간이 좀 걸렸지 만 이것이 설명하는 방식으로 작동하도록하는 가장 쉬운 방법이라는 것을 알게되었습니다. 이 작업을 수행하는 더 좋은 방법이있을 수 있지만 활동 코드를 게시하지 않았으므로 활동을 시작할 때 다음과 같은 목록이 있다고 즉석에서 가정해야합니다.

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 / 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프로젝트 에 대한 참조를 업데이트하는 것을 잊지 마십시오 .


3
안녕하세요,하지만 한 가지 의심이 있습니다. 필터에 하나의 문자를 입력하면 필터 결과가 있지만 하나 이상이면 아무것도 표시되지 않습니다. 그런 다음 표시됩니다. 왜?
나루토

안녕하세요, 자동 완성을 표시하기 전에 입력해야 할 기본 문자 수를 설정할 수 있으므로 EditText 또는 AutoCompleteTextView와 관련된 스타일을 확인하십시오. 사실 저는 기본값이 2 자라고 생각하므로이를 변경하려면 스타일에 추가해야 할 수도 있습니다.
tpbapp 2014 년

안녕하세요, 개발하는 동안 searchview의 한 가지 문제를 더 건너 왔습니다. 드롭 다운에 더 많은 항목을 표시하면 (예 : 3 개의 텍스트보기) 항목의 크기가 증가하므로 i.stack.imgur.com/d7t3A.png 처럼 스크롤하면 검색 항목이 키보드에 표시됩니다 . 이것은 텍스트 크기를 늘리거나 항목에 더 많은보기를 추가하면 발생합니다. 기본 동작입니까?
나루토

다시 한 번, 그런 일이 일어나서는 안됩니다. SearchView의 AutoCompleteTextView를 방해하는 프로젝트에 이미 많은 코드가 있거나 키보드 소프트웨어 및 앱 또는 플러그인에 문제가있어 이러한 동작을 일으키는 것 같습니다. 기본 동작은 다음과 같이해야한다 stackoverflow.com/questions/22116237/... 이 사람을 제외하고는 실제로 얻을하는 방법을 요구하고 있지 키보드 뒤에 숨겨진 될 수있다.
tpbapp

3
@tpbapp 나는 이미 그것을 알아 냈습니다. 제안 목록이 나타나지 않는 이유는 코드 search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));에서 onCreateOptionsMenu()loadHistory()메서드를 두 번 호출 했기 때문입니다 . 나는 SearchView 및 SearchManager 전역 변수 만이라고 할 그래서 getSearchableInfo()한 번 onCreateOptionsMenu(). 그리고 내 제안 목록이 이제 완벽하게 작동합니다. 코드를 수정하는 것이 좋습니다.
Hafizh Herdi 2014 년

52

다른 사람이 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"

자세한 내용은 여기 에서 업데이트 된 설명서를 참조하십시오 .


3
감사합니다. 내가 놓친 것만. :-)
Morten E. Rasmussen

간단하고 도움이되어 주셔서 감사합니다.
Muhammad

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

3

SearchDialog 또는 SearchWidget?

검색 기능을 구현할 때 공식 Android 개발자 문서에서 제안 하는 두 가지 접근 방식 이 있습니다. 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 두 가지 추상 방법이 있습니다

  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의 전체 작업 코드


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();
    }
    
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.