Bir RecyclerView ile SearchView nasıl filtrelenir


319

SearchViewDestek kütüphanesinden uygulamaya çalışıyorum . Kullanıcının SearchViewbir Listfilmleri filtrelemek için kullanmasını istiyorum RecyclerView.

Şimdiye kadar birkaç öğreticiler takip ettim ve eklemiş SearchViewiçin ActionBar, ama ben buradan nereye gerçekten emin değilim. Birkaç örnek gördüm ama yazmaya başladığınızda hiçbiri sonuç göstermiyor.

Bu benim MainActivity:

public class MainActivity extends ActionBarActivity {

    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    RecyclerView.Adapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        mAdapter = new CardAdapter() {
            @Override
            public Filter getFilter() {
                return null;
            }
        };
        mRecyclerView.setAdapter(mAdapter);
    }

    @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);
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Ve bu benim Adapter:

public abstract class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> implements Filterable {

    List<Movie> mItems;

    public CardAdapter() {
        super();
        mItems = new ArrayList<Movie>();
        Movie movie = new Movie();
        movie.setName("Spiderman");
        movie.setRating("92");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Doom 3");
        movie.setRating("91");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Transformers");
        movie.setRating("88");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Transformers 2");
        movie.setRating("87");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Transformers 3");
        movie.setRating("86");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Noah");
        movie.setRating("86");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Ironman");
        movie.setRating("86");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Ironman 2");
        movie.setRating("86");
        mItems.add(movie);

        movie = new Movie();
        movie.setName("Ironman 3");
        movie.setRating("86");
        mItems.add(movie);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycler_view_card_item, viewGroup, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        Movie movie = mItems.get(i);
        viewHolder.tvMovie.setText(movie.getName());
        viewHolder.tvMovieRating.setText(movie.getRating());
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder{

        public TextView tvMovie;
        public TextView tvMovieRating;

        public ViewHolder(View itemView) {
            super(itemView);
            tvMovie = (TextView)itemView.findViewById(R.id.movieName);
            tvMovieRating = (TextView)itemView.findViewById(R.id.movieRating);
        }
    }
}

Yanıtlar:


913

Giriş

Sorunuzla tam olarak neyle ilgili sorun yaşadığınız tam olarak açık olmadığından, bu özelliğin nasıl uygulanacağı ile ilgili bu kısa yolu yazdım; eğer hala sorularınız varsa sormaya çekinmeyin.

Bu GitHub Deposunda burada bahsettiğim her şeyin çalışma örneği var .
Örnek proje hakkında daha fazla bilgi edinmek isterseniz proje ana sayfasını ziyaret edin .

Her durumda sonuç şöyle görünmelidir:

demo görüntüsü

Demo uygulamasıyla ilk önce oynamak istiyorsanız Play Store'dan yükleyebilirsiniz:

Google Play'den indirin

Neyse başlayalım.


Kurulum SearchView

Klasörde res/menuyeni bir dosya oluşturun main_menu.xml. İçinde bir öğe eklemek ve set actionViewClassiçin android.support.v7.widget.SearchView. Destek kitaplığını kullandığınız için, actionViewClassözelliği ayarlamak için destek kitaplığının ad alanını kullanmanız gerekir . Xml dosyanızın şöyle görünmesi gerekir:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

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

</menu>

Sizin Fragmentya da Activityher zamanki gibi bu menüyü xml şişirmek zorundaysanız, o zaman MenuItemhangisini içerdiğini arayabilir SearchViewve OnQueryTextListeneriçine girilen metindeki değişiklikleri dinlemek için kullanacağımız uygulamayı uygulayabilirsiniz SearchView:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);

    final MenuItem searchItem = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView) searchItem.getActionView();
    searchView.setOnQueryTextListener(this);

    return true;
}

@Override
public boolean onQueryTextChange(String query) {
    // Here is where we are going to implement the filter logic
    return false;
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

Ve şimdi SearchViewkullanılmaya hazır. Filtre mantığını daha sonra onQueryTextChange()uygulamayı bitirdikten sonra uygulayacağız Adapter.


Kurulum Adapter

İlk ve en önemlisi, bu örnek için kullanacağım model sınıfı:

public class ExampleModel {

    private final long mId;
    private final String mText;

    public ExampleModel(long id, String text) {
        mId = id;
        mText = text;
    }

    public long getId() {
        return mId;
    }

    public String getText() {
        return mText;
    }
}

Bir metni görüntüleyecek olan sadece temel modeliniz RecyclerView. Bu metni görüntülemek için kullanacağım düzen:

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

    <data>

        <variable
            name="model"
            type="com.github.wrdlbrnft.searchablerecyclerviewdemo.ui.models.ExampleModel"/>

    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:clickable="true">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="@{model.text}"/>

    </FrameLayout>

</layout>

Gördüğünüz gibi Veri Bağlama kullanıyorum. Daha önce hiç veri bağlama ile çalışmadıysanız cesaretiniz kırılmasın! Çok basit ve güçlü, ancak bu cevap kapsamında nasıl çalıştığını açıklayamıyorum.

Bu ViewHolderiçin ExampleModelsınıfın:

public class ExampleViewHolder extends RecyclerView.ViewHolder {

    private final ItemExampleBinding mBinding;

    public ExampleViewHolder(ItemExampleBinding binding) {
        super(binding.getRoot());
        mBinding = binding;
    }

    public void bind(ExampleModel item) {
        mBinding.setModel(item);
    }
}

Yine özel bir şey yok. Sadece yukarıdaki xml düzeninde tanımladığımız gibi model sınıfını bu düzene bağlamak için veri bağlama kullanır.

Şimdi nihayet gerçekten ilginç kısma gelebiliriz: Adaptörün Yazılması. Ben temel uygulaması atlayacağım Adapterve bunun yerine bu cevap için ilgili bölümlere konsantre olacağım.

Ama önce konuşmamız gereken bir şey var: SortedListSınıf.


SortedList

SortedListBir parçası olan tamamen şaşırtıcı bir araçtır RecyclerViewkütüphanede. AdapterVeri setindeki değişiklikleri bildirmeye özen gösterir ve bunu çok verimli bir şekilde yapar. Yapmanız gereken tek şey öğelerin sırasını belirtmektir. Bunu compare(), SortedLista'daki gibi iki öğeyi karşılaştıran bir yöntem uygulayarak yapmanız gerekir Comparator. Ama sıralamak yerine List, öğeleri sıralamak için kullanılır RecyclerView!

Uygulamanız SortedListgereken Adapterbir Callbacksınıf aracılığıyla etkileşime girer :

private final SortedList.Callback<ExampleModel> mCallback = new SortedList.Callback<ExampleModel>() {

    @Override
    public void onInserted(int position, int count) {
         mAdapter.notifyItemRangeInserted(position, count);
    }

    @Override
    public void onRemoved(int position, int count) {
        mAdapter.notifyItemRangeRemoved(position, count);
    }

    @Override
    public void onMoved(int fromPosition, int toPosition) {
        mAdapter.notifyItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onChanged(int position, int count) {
        mAdapter.notifyItemRangeChanged(position, count);
    }

    @Override
    public int compare(ExampleModel a, ExampleModel b) {
        return mComparator.compare(a, b);
    }

    @Override
    public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
        return oldItem.equals(newItem);
    }

    @Override
    public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
        return item1.getId() == item2.getId();
    }
}

Gibi callback'inde üstündeki yöntemlerinde onMoved, onInsertedvb Eşdeğer aramalarınızdan yöntemini bildirmek aramak zorunda Adapter. Üç altındaki yöntemleri compare, areContentsTheSameve areItemsTheSamebu nesneler ekranda görünmelidir sipariş ne tür nesnelerin görüntülemek istediğiniz ne ve ya uygun uygulamak zorunda.

Bu yöntemleri tek tek inceleyelim:

@Override
public int compare(ExampleModel a, ExampleModel b) {
    return mComparator.compare(a, b);
}

Bu compare()daha önce konuştuğumuz yöntemi. Bu örnekte sadece Comparatoriki modeli karşılaştıran bir çağrıya geçiyorum . Öğelerin ekranda alfabetik sırada görünmesini istiyorsanız. Bu karşılaştırıcı şöyle görünebilir:

private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
    @Override
    public int compare(ExampleModel a, ExampleModel b) {
        return a.getText().compareTo(b.getText());
    }
};

Şimdi bir sonraki yönteme bakalım:

@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
    return oldItem.equals(newItem);
}

Bu yöntemin amacı, bir modelin içeriğinin değişip değişmediğini belirlemektir. Bunu SortedList, bir değişiklik olayının başlatılması gerekip gerekmediğini belirlemek için kullanır; başka bir deyişle RecyclerView, eski ve yeni sürümü crossfade etmelidir. Eğer sınıfları doğru equals()ve hashCode()uygulamanız varsa, genellikle yukarıdaki gibi uygulayabilirsiniz. Sınıfa bir equals()ve hashCode()uygulama eklersek ExampleModel, şöyle görünmelidir:

public class ExampleModel implements SortedListAdapter.ViewModel {

    private final long mId;
    private final String mText;

    public ExampleModel(long id, String text) {
        mId = id;
        mText = text;
    }

    public long getId() {
        return mId;
    }

    public String getText() {
        return mText;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ExampleModel model = (ExampleModel) o;

        if (mId != model.mId) return false;
        return mText != null ? mText.equals(model.mText) : model.mText == null;

    }

    @Override
    public int hashCode() {
        int result = (int) (mId ^ (mId >>> 32));
        result = 31 * result + (mText != null ? mText.hashCode() : 0);
        return result;
    }
}

Hızlı yan not: Android Studio, IntelliJ ve Eclipse gibi çoğu IDE , bir düğmeye basarak sizin için oluşturma equals()ve hashCode()uygulama işlevlerine sahiptir ! Yani onları kendiniz uygulamak zorunda değilsiniz. İnternette IDE'nizde nasıl çalıştığını görün!

Şimdi son yönteme bir göz atalım:

@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
    return item1.getId() == item2.getId();
}

SortedListÖğenin aynı şeyi gösterirler olmadığını kontrol için bu yöntemi kullanır. En basit ifadeyle (nasıl SortedListçalıştığını açıklamadan ) bu, bir nesnenin zaten içerilmiş olup olmadığını Listve bir ekleme, taşıma veya değiştirme animasyonunun oynatılması gerekip gerekmediğini belirlemek için kullanılır . Modellerinizin bir kimliği varsa, genellikle bu yöntemdeki kimliği karşılaştırabilirsiniz. Eğer yapmazlarsa, bunu kontrol etmenin başka bir yolunu bulmanız gerekir, ancak bunu uygulamanız sonuç olarak uygulamanıza bağlıdır. Genellikle tüm modellere bir kimlik vermek en basit seçenektir - örneğin, bir veritabanındaki verileri sorguluyorsanız birincil anahtar alanı olabilir.

İle SortedList.Callbackdoğru bir şekilde uygulandığında biz bir örneğini oluşturabilir SortedList:

final SortedList<ExampleModel> list = new SortedList<>(ExampleModel.class, mCallback);

Yapıcıdaki ilk parametre olarak SortedListmodellerinizin sınıfını geçmeniz gerekir. Diğer parametre sadece SortedList.Callbackyukarıda tanımladığımızdır.

Şimdi işe başlayalım: Eğer Adapterbir ile uygularsak SortedListşöyle bir şey olmalı:

public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {

    private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
        @Override
        public int compare(ExampleModel a, ExampleModel b) {
            return mComparator.compare(a, b);
        }

        @Override
        public void onInserted(int position, int count) {
            notifyItemRangeInserted(position, count);
        }

        @Override
        public void onRemoved(int position, int count) {
            notifyItemRangeRemoved(position, count);
        }

        @Override
        public void onMoved(int fromPosition, int toPosition) {
            notifyItemMoved(fromPosition, toPosition);
        }

        @Override
        public void onChanged(int position, int count) {
            notifyItemRangeChanged(position, count);
        }

        @Override
        public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
            return oldItem.equals(newItem);
        }

        @Override
        public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
            return item1.getId() == item2.getId();
        }
    });

    private final LayoutInflater mInflater;
    private final Comparator<ExampleModel> mComparator;

    public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
        mInflater = LayoutInflater.from(context);
        mComparator = comparator;
    }

    @Override
    public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
        return new ExampleViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(ExampleViewHolder holder, int position) {
        final ExampleModel model = mSortedList.get(position);
        holder.bind(model);
    }

    @Override
    public int getItemCount() {
        return mSortedList.size();
    }
}

ComparatorAynı kullanabilmesi madde yapıcı içinden geçirilir sıralamak için kullanılan Adapteröğeler farklı bir sırada görüntülenecek gerekiyordu bile.

Şimdi neredeyse bitti! Ancak, önce öğeye öğe eklemek veya kaldırmak için bir yola ihtiyacımız var Adapter. Bu amaçla, aşağıdakilere Adapteröğe eklememize ve kaldırmamıza izin veren yöntemler ekleyebiliriz SortedList:

public void add(ExampleModel model) {
    mSortedList.add(model);
}

public void remove(ExampleModel model) {
    mSortedList.remove(model);
}

public void add(List<ExampleModel> models) {
    mSortedList.addAll(models);
}

public void remove(List<ExampleModel> models) {
    mSortedList.beginBatchedUpdates();
    for (ExampleModel model : models) {
        mSortedList.remove(model);
    }
    mSortedList.endBatchedUpdates();
}

Burada herhangi bir bildirim yöntemini çağırmamız gerekmez, çünkü SortedListzaten bunu SortedList.Callback! Bunun yanı sıra, bu yöntemlerin uygulanması bir istisna dışında oldukça basittir: bir Listmodeli kaldıran kaldır yöntemi . Yana SortedListbiz liste üzerinde döngü gereken tek bir nesneyi kaldırmak ve tek modeller birini kaldırmak edebilecek tek kaldır yöntemi vardır. Arayan beginBatchedUpdates()biz yapacağız başlayan toplu Tüm değişikliklere SortedListbirlikte ile ve performansı artırır. Dediğimiz zaman bir kerede tüm değişiklikler hakkında bilgilendirilir.endBatchedUpdates()RecyclerView

Ek olarak, anlamanız gereken şey, içine bir nesne eklerseniz SortedListve zaten içinde bulunuyorsa, SortedListtekrar eklenmeyecektir. Bunun yerine, nesnenin değişip değişmediğini ve öğede öğenin olup olmadığını anlamak SortedListiçin areContentsTheSame()yöntemi kullanır RecyclerView.

Her neyse, genellikle tercih ettiğim, bir RecyclerViewkerede tüm öğeleri değiştirmeme izin veren bir yöntemdir . İçinde olmayan her şeyi kaldırın Listve eksik olan tüm öğeleri ekleyin SortedList:

public void replaceAll(List<ExampleModel> models) {
    mSortedList.beginBatchedUpdates();
    for (int i = mSortedList.size() - 1; i >= 0; i--) {
        final ExampleModel model = mSortedList.get(i);
        if (!models.contains(model)) {
            mSortedList.remove(model);
        }
    }
    mSortedList.addAll(models);
    mSortedList.endBatchedUpdates();
}

Bu yöntem, performansı artırmak için tüm güncelleştirmeleri toplu olarak bir araya getirir. İlk döngü, başlangıçta bir öğeyi kaldırmak, ondan sonra gelen tüm öğelerin dizinlerini bozacağından ve bazı durumlarda veri tutarsızlıkları gibi sorunlara yol açabileceğinden tersidir. Sonra biz sadece eklemek Listiçin SortedListkullanma addAll()henüz bulunmayan tüm öğeler eklemek için SortedListve - yukarıda açıklanan gibi - güncelleme zaten tüm öğeleri SortedListama değişti.

Ve bununla birlikte Adaptertamamlandı. Her şey şöyle görünmelidir:

public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {

    private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
        @Override
        public int compare(ExampleModel a, ExampleModel b) {
            return mComparator.compare(a, b);
        }

        @Override
        public void onInserted(int position, int count) {
            notifyItemRangeInserted(position, count);
        }

        @Override
        public void onRemoved(int position, int count) {
            notifyItemRangeRemoved(position, count);
        }

        @Override
        public void onMoved(int fromPosition, int toPosition) {
            notifyItemMoved(fromPosition, toPosition);
        }

        @Override
        public void onChanged(int position, int count) {
            notifyItemRangeChanged(position, count);
        }

        @Override
        public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
            return oldItem.equals(newItem);
        }

        @Override
        public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
            return item1 == item2;
        }
    });

    private final Comparator<ExampleModel> mComparator;
    private final LayoutInflater mInflater;

    public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
        mInflater = LayoutInflater.from(context);
        mComparator = comparator;
    }

    @Override
    public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final ItemExampleBinding binding = ItemExampleBinding.inflate(mInflater, parent, false);
        return new ExampleViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(ExampleViewHolder holder, int position) {
        final ExampleModel model = mSortedList.get(position);
        holder.bind(model);
    }

    public void add(ExampleModel model) {
        mSortedList.add(model);
    }

    public void remove(ExampleModel model) {
        mSortedList.remove(model);
    }

    public void add(List<ExampleModel> models) {
        mSortedList.addAll(models);
    }

    public void remove(List<ExampleModel> models) {
        mSortedList.beginBatchedUpdates();
        for (ExampleModel model : models) {
            mSortedList.remove(model);
        }
        mSortedList.endBatchedUpdates();
    }

    public void replaceAll(List<ExampleModel> models) {
        mSortedList.beginBatchedUpdates();
        for (int i = mSortedList.size() - 1; i >= 0; i--) {
            final ExampleModel model = mSortedList.get(i);
            if (!models.contains(model)) {
                mSortedList.remove(model);
            }
        }
        mSortedList.addAll(models);
        mSortedList.endBatchedUpdates();
    }

    @Override
    public int getItemCount() {
        return mSortedList.size();
    }
}

Şimdi eksik olan tek şey filtrelemeyi uygulamak!


Filtre mantığını uygulama

Filtre mantığını uygulamak için önce Listolası tüm modellerden birini tanımlamamız gerekir . Bu örnek için ben oluşturmak Listait ExampleModelfilmlerin bir diziden durumlarda:

private static final String[] MOVIES = new String[]{
        ...
};

private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
    @Override
    public int compare(ExampleModel a, ExampleModel b) {
        return a.getText().compareTo(b.getText());
    }
};

private ExampleAdapter mAdapter;
private List<ExampleModel> mModels;
private RecyclerView mRecyclerView;

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

    mAdapter = new ExampleAdapter(this, ALPHABETICAL_COMPARATOR);

    mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
    mBinding.recyclerView.setAdapter(mAdapter);

    mModels = new ArrayList<>();
    for (String movie : MOVIES) {
        mModels.add(new ExampleModel(movie));
    }
    mAdapter.add(mModels);
}

Burada özel bir şey yok, biz sadece somutlaştırıyoruz Adapterve RecyclerView. Bundan sonra dizideki Listfilm adlarından bir model oluşturuyoruz MOVIES. Sonra tüm modelleri SortedList.

Şimdi onQueryTextChange()daha önce tanımladığımız geri dönebilir ve filtre mantığını uygulamaya başlayabiliriz:

@Override
public boolean onQueryTextChange(String query) {
    final List<ExampleModel> filteredModelList = filter(mModels, query);
    mAdapter.replaceAll(filteredModelList);
    mBinding.recyclerView.scrollToPosition(0);
    return true;
}

Bu yine oldukça basit. Biz yöntemini çağırın filter()ve geçmek Listarasında ExampleModeliyi sorgu dizesi gibi s. Sonra diyoruz replaceAll()üzerinde Adapterve filtrelenmiş geçmek Listtarafından döndürülen filter(). Ayrıca aramak zorunda scrollToPosition(0)üzerine RecyclerViewbir şeyler ararken kullanıcı her zaman tüm öğeleri görebilirsiniz sağlamak için. Aksi takdirde, RecyclerViewfiltreleme sırasında aşağı kaydırılmış konumda kalabilir ve daha sonra birkaç öğeyi gizleyebilir. En üste kaydırmak arama yaparken daha iyi bir kullanıcı deneyimi sağlar.

Şimdi geriye kalan tek şey filter()kendini uygulamaktır :

private static List<ExampleModel> filter(List<ExampleModel> models, String query) {
    final String lowerCaseQuery = query.toLowerCase();

    final List<ExampleModel> filteredModelList = new ArrayList<>();
    for (ExampleModel model : models) {
        final String text = model.getText().toLowerCase();
        if (text.contains(lowerCaseQuery)) {
            filteredModelList.add(model);
        }
    }
    return filteredModelList;
}

Burada yaptığımız ilk şey toLowerCase(), sorgu dizesine çağrı yapmaktır . Arama fonksiyonumuzun büyük / küçük harfe duyarlı olmasını istemiyoruz ve toLowerCase()karşılaştırdığımız tüm dizeleri çağırarak , durumdan bağımsız olarak aynı sonuçları döndürmemizi sağlayabiliriz. Daha sonra, Listiçine geçirdiğimiz tüm modeller arasında yinelenir ve sorgu dizesinin model metninde olup olmadığını kontrol eder. Eğer öyleyse, model filtreye eklenir List.

Ve bu kadar! Yukarıdaki kod API seviye 7 ve üstünde çalışır ve API seviye 11 ile başlayarak ücretsiz olarak öğe animasyonları alırsınız!

Bunun çok ayrıntılı bir açıklama olduğunu anlıyorum, bu muhtemelen her şeyi olduğundan daha karmaşık görünüyor, ancak tüm sorunu genelleştirebilmemizi ve uygulamayı çok daha basit Adapterbir temelde yapmanın bir yolu var SortedList.


Sorunu genelleme ve Bağdaştırıcıyı basitleştirme

Bu bölümde fazla ayrıntıya girmeyeceğim - kısmen Stack Overflow'daki cevaplar için karakter sınırına karşı koştuğum için değil, aynı zamanda çoğu yukarıda açıklandığı için - ama değişiklikleri özetlemek için: Bir temel Adaptersınıf uygulayabiliriz zaten örneklerle SortedListbağlamanın yanı sıra modellerle başa çıkmaya özen gösterir ViewHolderve Adaptera SortedList. Bunun için iki şey yapmalıyız:

  • ViewModelTüm model sınıflarının uygulamak zorunda olduğu bir arayüz oluşturmamız gerekiyor
  • Modelleri otomatik olarak bağlamak için kullanabileceğiniz ViewHolderbir bind()yöntemi tanımlayan bir alt sınıf yaratmamız gerekir Adapter.

Bu, sadece RecyclerViewmodelleri uygulayarak ve karşılık gelen ViewHolderuygulamaları uygulayarak görüntülenmesi gereken içeriğe odaklanmamızı sağlar . Bu temel sınıf kullanma biz karmaşık detayları hakkında endişe gerekmez Adapterve onun SortedList.

SortedListAdapter

Çünkü bu temel sınıf uygulayan ve hatta burada tam kaynak kodu ekleyin, ancak bu temel sınıf tam kaynak kodu bulabilirsiniz her bir adımına devam edemez StackOverflow I cevapları için karakter sınırı - Ben denilen SortedListAdapter- bunda GitHub Gist .

Hayatınızı kolaylaştırmak için jCenter'da içeren bir kütüphane yayınladım SortedListAdapter! Kullanmak istiyorsanız, yapmanız gereken tek şey bu bağımlılığı uygulamanızın build.gradle dosyasına eklemektir:

compile 'com.github.wrdlbrnft:sorted-list-adapter:0.2.0.1'

Bu kütüphane hakkında daha fazla bilgiyi kütüphane ana sayfasında bulabilirsiniz .

SortedListAdapter kullanma

Kullanmak SortedListAdapteriçin iki değişiklik yapmalıyız:

  • Değişim ViewHoldero uzanacak şekilde SortedListAdapter.ViewHolder. Type parametresi, buna bağlı olması gereken model olmalıdır ViewHolder- bu durumda ExampleModel. Bunun performBind()yerine verileri modellerinize bağlamak zorundasınız bind().

    public class ExampleViewHolder extends SortedListAdapter.ViewHolder<ExampleModel> {
    
        private final ItemExampleBinding mBinding;
    
        public ExampleViewHolder(ItemExampleBinding binding) {
            super(binding.getRoot());
            mBinding = binding;
        }
    
        @Override
        protected void performBind(ExampleModel item) {
            mBinding.setModel(item);
        }
    }
  • Tüm modellerinizin ViewModelarayüzü uyguladığından emin olun :

    public class ExampleModel implements SortedListAdapter.ViewModel {
        ...
    }

Bundan sonra, artık ihtiyacımız olmayan her şeyi ExampleAdaptergenişletmek SortedListAdapterve kaldırmak için güncellememiz gerekiyor. Type parametresi, birlikte çalıştığınız model türü olmalıdır - bu durumda ExampleModel. Ancak farklı modellerle çalışıyorsanız, type parametresini olarak ayarlayın ViewModel.

public class ExampleAdapter extends SortedListAdapter<ExampleModel> {

    public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
        super(context, ExampleModel.class, comparator);
    }

    @Override
    protected ViewHolder<? extends ExampleModel> onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) {
        final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
        return new ExampleViewHolder(binding);
    }

    @Override
    protected boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
        return item1.getId() == item2.getId();
    }

    @Override
    protected boolean areItemContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
        return oldItem.equals(newItem);
    }
}

Ondan sonra işimiz bitti! Söz etmek Ancak son bir şey: SortedListAdapterAynı yoktur add(), remove()ya replaceAll()orijinal yöntemleri ExampleAdaptervardı. EditorListedeki yöntemle erişilebilen öğeleri değiştirmek için ayrı bir nesne kullanır edit(). Bu nedenle, çağırmanız gereken öğeleri kaldırmak veya eklemek istiyorsanız edit(), bu Editorörneğe öğeleri ekleyin ve kaldırın ve işiniz bittiğinde, commit()değişiklikleri aşağıdakilere uygulamak için çağırın SortedList:

mAdapter.edit()
        .remove(modelToRemove)
        .add(listOfModelsToAdd)
        .commit();

Bu şekilde yaptığınız tüm değişiklikler performansı artırmak için bir araya getirilir. replaceAll()Yukarıdaki bölümlerde uygulanan yöntem, aynı zamanda, bu üzerinde mevcut olan Editorbir nesne:

mAdapter.edit()
        .replaceAll(mModels)
        .commit();

Telefon etmeyi unutursanız commit(), değişikliklerinizin hiçbiri uygulanmaz!


4
@TiagoOliveira Eh sadece kutunun dışında çalışmak için yapılmış: D Veri bağlama, aşina olmayan insanlar için bir engeldir, ama yine de dahil ettim çünkü şaşırtıcı ve teşvik etmek istiyorum. Bir nedenden dolayı pek çok insan bunu bilmiyor gibi görünüyor ...
Xaver Kapeller

78
Henüz tüm cevabı okumadım, bu yorumu yazmak için okumamı yarıda bir yerde duraklatmak zorunda kaldım - bu, burada SO'da bulduğum en iyi cevaplardan biri! Teşekkürler!
daneejela

16
Sadece nasıl olduğunuzu seviyorum: "Sorunuzdan neyle sorun yaşadığınız açık değil, bu yüzden işte tam yaptığım tam bir örnek": D
Fred

7
+ 1 bize sadece Veri Bağlama Android var olduğunu göstermek için! Bunu hiç duymadım ve kullanmaya başlayacağım gibi görünüyor. Teşekkürler
Jorge Casariego

6
Bu çözüm gülünç derecede uzun ve genellikle aşırı mühendislikle konuşuluyor. İkincisi için gidin.
Enrico Casini

194

Tek yapmanız gereken filteryöntem eklemek RecyclerView.Adapter:

public void filter(String text) {
    items.clear();
    if(text.isEmpty()){
        items.addAll(itemsCopy);
    } else{
        text = text.toLowerCase();
        for(PhoneBookItem item: itemsCopy){
            if(item.name.toLowerCase().contains(text) || item.phone.toLowerCase().contains(text)){
                items.add(item);
            }
        }
    }
    notifyDataSetChanged();
}

itemsCopygibi adaptörün yapıcısında başlatılır itemsCopy.addAll(items).

Bunu yaparsanız, sadece ara filterdan OnQueryTextListener:

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        adapter.filter(query);
        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        adapter.filter(newText);
        return true;
    }
});

Telefon defterimi ada ve telefon numarasına göre filtrelemeye bir örnek.


11
Bunun kabul edilen cevap olması gerektiğini düşünüyorum. Daha basit ve işe yarıyor
Jose_GD 2

6
Basit ve verimli!
AlxDroidDev

11
@Xaver Kapeller yanıtı yerine bu yaklaşımı uygularsanız animasyonu kaybedeceğinizi unutmayın.
17'de

23
Çok uzun olduğu için kabul edilen cevabı denemedim. Bu cevap işe yarar ve uygulanması kolaydır. Menü öğeniz XML'e "app: actionViewClass =" android.support.v7.widget.SearchView "eklemeyi unutmayın.
SajithK

3
Öğeler ve öğeler tam olarak nedir?
Lucky_girl

82

@Shruthi Kamoji'yi daha temiz bir şekilde takip ederek, bunun için kastedilebilir bir filtreyi kullanabiliriz:

public abstract class GenericRecycleAdapter<E> extends RecyclerView.Adapter implements Filterable
{
    protected List<E> list;
    protected List<E> originalList;
    protected Context context;

    public GenericRecycleAdapter(Context context,
    List<E> list)
    {
        this.originalList = list;
        this.list = list;
        this.context = context;
    }

    ...

    @Override
    public Filter getFilter() {
        return new Filter() {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                list = (List<E>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                List<E> filteredResults = null;
                if (constraint.length() == 0) {
                    filteredResults = originalList;
                } else {
                    filteredResults = getFilteredResults(constraint.toString().toLowerCase());
                }

                FilterResults results = new FilterResults();
                results.values = filteredResults;

                return results;
            }
        };
    }

    protected List<E> getFilteredResults(String constraint) {
        List<E> results = new ArrayList<>();

        for (E item : originalList) {
            if (item.getName().toLowerCase().contains(constraint)) {
                results.add(item);
            }
        }
        return results;
    }
} 

Buradaki E, bir Genel Türdür, sınıfınızı kullanarak genişletebilirsiniz:

public class customerAdapter extends GenericRecycleAdapter<CustomerModel>

Veya sadece E'yi istediğiniz türe değiştirin ( <CustomerModel>örneğin)

Ardından searchView'den (menu.xml dosyasına koyabileceğiniz widget):

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String text) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String text) {
        yourAdapter.getFilter().filter(text);
        return true;
    }
});

Ben böyle bir şey kullanıyorum! İnce ve genel örnek çalışır!
Mateus

Merhaba, bana bu konuda adım adım yardımcı olabilecek: stackoverflow.com/questions/40754174/…
Thorvald Olavsen

En temiz cevap!
adalpari

4
PerformFiltering yönteminde bir çalışan iş parçacığı üzerinde işlem yapıldığı için bu, oylanan cevaptan çok daha iyidir.
Hmmm

1
Ancak aynı listeye farklı değişkenlere bir başvuru atarsınız. Örneğin this.originalList = liste; Bunun yerine addAll kullanmalı veya listeyi ArrayList yapıcısı
Florian Walther'da

5

sadece bir orignal ve bir temp adaptöründe iki liste oluşturun ve Filtrelenebilir'i uygular .

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                final FilterResults oReturn = new FilterResults();
                final ArrayList<T> results = new ArrayList<>();
                if (origList == null)
                    origList = new ArrayList<>(itemList);
                if (constraint != null && constraint.length() > 0) {
                    if (origList != null && origList.size() > 0) {
                        for (final T cd : origList) {
                            if (cd.getAttributeToSearch().toLowerCase()
                                    .contains(constraint.toString().toLowerCase()))
                                results.add(cd);
                        }
                    }
                    oReturn.values = results;
                    oReturn.count = results.size();//newly Aded by ZA
                } else {
                    oReturn.values = origList;
                    oReturn.count = origList.size();//newly added by ZA
                }
                return oReturn;
            }

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(final CharSequence constraint,
                                          FilterResults results) {
                itemList = new ArrayList<>((ArrayList<T>) results.values);
                // FIXME: 8/16/2017 implement Comparable with sort below
                ///Collections.sort(itemList);
                notifyDataSetChanged();
            }
        };
    }

nerede

public GenericBaseAdapter(Context mContext, List<T> itemList) {
        this.mContext = mContext;
        this.itemList = itemList;
        this.origList = itemList;
    }

Güzel çözüm. İki liste oluşturdum ve basit bir filtre yöntemi kullandım. Bir öğe için doğru bağdaştırıcı konumunu bir sonraki Etkinliğe geçiremiyorum. Bunun için önerebileceğiniz herhangi bir düşünce veya fikri takdir ediyorum: stackoverflow.com/questions/46027110/…
AJW

4

Adaptörde:

public void setFilter(List<Channel> newList){
        mChannels = new ArrayList<>();
        mChannels.addAll(newList);
        notifyDataSetChanged();
    }

Faaliyette:

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                newText = newText.toLowerCase();
                ArrayList<Channel> newList = new ArrayList<>();
                for (Channel channel: channels){
                    String channelName = channel.getmChannelName().toLowerCase();
                    if (channelName.contains(newText)){
                        newList.add(channel);
                    }
                }
                mAdapter.setFilter(newList);
                return true;
            }
        });

3

İle Android Mimarisi Bileşenlerinin kullanımı yoluyla LiveData bu kolayca herhangi bir tür uygulanabilir Adaptörü . Aşağıdaki adımları uygulamanız yeterlidir:

1. Aşağıdaki örnekte olduğu gibi verilerinizi Oda Veritabanından LiveData olarak dönecek şekilde ayarlayın:

@Dao
public interface CustomDAO{

@Query("SELECT * FROM words_table WHERE column LIKE :searchquery")
    public LiveData<List<Word>> searchFor(String searchquery);
}

2. DAO'nuzu ve kullanıcı arayüzünüzü bağlayacak bir yöntemle verilerinizi canlı olarak güncellemek için bir ViewModel nesnesi oluşturun

public class CustomViewModel extends AndroidViewModel {

    private final AppDatabase mAppDatabase;

    public WordListViewModel(@NonNull Application application) {
        super(application);
        this.mAppDatabase = AppDatabase.getInstance(application.getApplicationContext());
    }

    public LiveData<List<Word>> searchQuery(String query) {
        return mAppDatabase.mWordDAO().searchFor(query);
    }

}

3. Aşağıdaki gibi onQueryTextListener üzerinden sorguyu ileterek verilerinizi anında ViewModel'den çağırın:

İçeride onCreateOptionsMenudinleyicinizi aşağıdaki gibi ayarlayın

searchView.setOnQueryTextListener(onQueryTextListener);

Sorgu dinleyicinizi SearchActivity sınıfınızda bir yere aşağıdaki gibi kurun

private android.support.v7.widget.SearchView.OnQueryTextListener onQueryTextListener =
            new android.support.v7.widget.SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    getResults(query);
                    return true;
                }

                @Override
                public boolean onQueryTextChange(String newText) {
                    getResults(newText);
                    return true;
                }

                private void getResults(String newText) {
                    String queryText = "%" + newText + "%";
                    mCustomViewModel.searchQuery(queryText).observe(
                            SearchResultsActivity.this, new Observer<List<Word>>() {
                                @Override
                                public void onChanged(@Nullable List<Word> words) {
                                    if (words == null) return;
                                    searchAdapter.submitList(words);
                                }
                            });
                }
            };

Not : Adımlar (1.) ve (2.) standart AAC ViewModel ve DAO uygulamasıdır, burada devam eden tek gerçek "büyü" , sorgu metni değiştikçe listenizin sonuçlarını dinamik olarak güncelleyecek olan OnQueryTextListener'dadır .

Konuyla ilgili daha fazla açıklamaya ihtiyacınız varsa, lütfen sormaktan çekinmeyin. Umarım bu yardımcı olmuştur :).


1

Bu, filtreleme animasyonunu kaybetmemek için @klimat yanıtını genişletme konusundaki benim düşüncem.

public void filter(String query){
    int completeListIndex = 0;
    int filteredListIndex = 0;
    while (completeListIndex < completeList.size()){
        Movie item = completeList.get(completeListIndex);
        if(item.getName().toLowerCase().contains(query)){
            if(filteredListIndex < filteredList.size()) {
                Movie filter = filteredList.get(filteredListIndex);
                if (!item.getName().equals(filter.getName())) {
                    filteredList.add(filteredListIndex, item);
                    notifyItemInserted(filteredListIndex);
                }
            }else{
                filteredList.add(filteredListIndex, item);
                notifyItemInserted(filteredListIndex);
            }
            filteredListIndex++;
        }
        else if(filteredListIndex < filteredList.size()){
            Movie filter = filteredList.get(filteredListIndex);
            if (item.getName().equals(filter.getName())) {
                filteredList.remove(filteredListIndex);
                notifyItemRemoved(filteredListIndex);
            }
        }
        completeListIndex++;
    }
}

Temel olarak, tam bir listeye bakmak ve filtrelenmiş bir listeye birer birer öğe eklemek / kaldırmaktır.


0

Bağdaştırıcı listesinin filtre listesinden daha küçük bir boyuta sahip olması ve IndexOutOfBoundsException gerçekleştiği için aranan metni temizledikten sonra (filtre artık çalışmadı) bir sorunu önlemek için @Xaver Kapeller'in çözümünü 2 şeyle değiştirmenizi öneririz. Kodun aşağıdaki gibi değiştirilmesi gerekiyor

public void addItem(int position, ExampleModel model) {
    if(position >= mModel.size()) {
        mModel.add(model);
        notifyItemInserted(mModel.size()-1);
    } else {
        mModels.add(position, model);
        notifyItemInserted(position);
    }
}

Ve moveItem işlevselliğinde de değiştirin

public void moveItem(int fromPosition, int toPosition) {
    final ExampleModel model = mModels.remove(fromPosition);
    if(toPosition >= mModels.size()) {
        mModels.add(model);
        notifyItemMoved(fromPosition, mModels.size()-1);
    } else {
        mModels.add(toPosition, model);
        notifyItemMoved(fromPosition, toPosition); 
    }
}

Size yardımcı olabileceğini umuyoruz!


Bu hiç gerekli değil.
Xaver Kapeller

Orijinal yanıt için IndexOutOfBoundsException olacağını yapmazsanız, neden gerekli değil ???? Bir kayıt ister misin? @XaverKapeller
toidv

Hiçbir istisna sadece Adapteryanlış şekilde uygularsanız gerçekleşmez . Kodunuzu görmeden en olası sorun listenin bir kopyasını tüm öğeleri ile geçmiyor sanırım Adapter.
Xaver Kapeller

Hata günlüğü: W / System.err: java.lang.IndexOutOfBoundsException: Geçersiz dizin 36, boyut 35 W / System.err: java.util.ArrayList.throwIndexOutOfBoundsException (ArrayList.java:255) W / System.err: java.util.ArrayList.add (ArrayList.java:147) adresinde W / System.err: at com.quomodo.inploi.ui.adapter.MultipleSelectFilterAdapter.addItem (MultipleSelectFilterAdapter.java:125) W / System.err: com'da .quomodo.inploi.ui.adapter.MultipleSelectFilterAdapter.applyAndAnimateAdditions (MultipleSelectFilterAdapter.java:78)
toidv 13:16

Lütfen aşağıdaki kaynak kodunu kontrol etmeye yardımcı olun @XaverKapeller gist.github.com/toidv/fe71dc45169e4138271b52fdb29420c5
toidv

0

Arama görünümü ve tıklama listecisi ile geri dönüşüm görünümü

Adaptörünüze bir arayüz ekleyin.

public interface SelectedUser{

    void selectedUser(UserModel userModel);

}

arayüzü etkinliğinize uygulayın ve yöntemi geçersiz kılın. @ Herkese açık boşluğu geçersiz kıl seçilen Kullanıcı (UserModel userModel) {

    startActivity(new Intent(MainActivity.this, SelectedUserActivity.class).putExtra("data",userModel));



}

Tam öğretici ve kaynak kodu: Searchview ve onclicklistener ile geri dönüşüm görünümü


-1

Aynı sorunu içindeki bazı değişikliklerle bağlantıyı kullanarak çözdüm. Filtre ile RecyclerView üzerinde arama filtresi. Hatta mümkün mü? (Bu yardımcı olur umarım).

İşte adaptör sınıfım

public class ContactListRecyclerAdapter extends RecyclerView.Adapter<ContactListRecyclerAdapter.ContactViewHolder> implements Filterable {

Context mContext;
ArrayList<Contact> customerList;
ArrayList<Contact> parentCustomerList;


public ContactListRecyclerAdapter(Context context,ArrayList<Contact> customerList)
{
    this.mContext=context;
    this.customerList=customerList;
    if(customerList!=null)
    parentCustomerList=new ArrayList<>(customerList);
}

   // other overrided methods

@Override
public Filter getFilter() {
    return new FilterCustomerSearch(this,parentCustomerList);
}
}

// Filtre sınıfı

import android.widget.Filter;
import java.util.ArrayList;


public class FilterCustomerSearch extends Filter
{
private final ContactListRecyclerAdapter mAdapter;
ArrayList<Contact> contactList;
ArrayList<Contact> filteredList;

public FilterCustomerSearch(ContactListRecyclerAdapter mAdapter,ArrayList<Contact> contactList) {
    this.mAdapter = mAdapter;
    this.contactList=contactList;
    filteredList=new ArrayList<>();
}

@Override
protected FilterResults performFiltering(CharSequence constraint) {
    filteredList.clear();
    final FilterResults results = new FilterResults();

    if (constraint.length() == 0) {
        filteredList.addAll(contactList);
    } else {
        final String filterPattern = constraint.toString().toLowerCase().trim();

        for (final Contact contact : contactList) {
            if (contact.customerName.contains(constraint)) {
                filteredList.add(contact);
            }
            else if (contact.emailId.contains(constraint))
            {
                filteredList.add(contact);

            }
            else if(contact.phoneNumber.contains(constraint))
                filteredList.add(contact);
        }
    }
    results.values = filteredList;
    results.count = filteredList.size();
    return results;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    mAdapter.customerList.clear();
    mAdapter.customerList.addAll((ArrayList<Contact>) results.values);
    mAdapter.notifyDataSetChanged();
}

}

// Etkinlik sınıfı

public class HomeCrossFadeActivity extends AppCompatActivity implements View.OnClickListener,OnFragmentInteractionListener,OnTaskCompletedListner
{
Fragment fragment;
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_homecrossfadeslidingpane2);CardView mCard;
   setContentView(R.layout.your_main_xml);}
   //other overrided methods
  @Override
   public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.

    MenuInflater inflater = getMenuInflater();
    // Inflate menu to add items to action bar if it is present.
    inflater.inflate(R.menu.menu_customer_view_and_search, menu);
    // Associate searchable configuration with the SearchView
    SearchManager searchManager =
            (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView =
            (SearchView) menu.findItem(R.id.menu_search).getActionView();
    searchView.setQueryHint("Search Customer");
    searchView.setSearchableInfo(
            searchManager.getSearchableInfo(getComponentName()));

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            if(fragment instanceof CustomerDetailsViewWithModifyAndSearch)
                ((CustomerDetailsViewWithModifyAndSearch)fragment).adapter.getFilter().filter(newText);
            return false;
        }
    });



    return true;
}
}

OnQueryTextChangeListener () yönteminde bağdaştırıcınızı kullanın. Benim adpter parçalı olduğu için bunu parçalara ayırdım. Bağdaştırıcı, etkinlik sınıfınızdaysa doğrudan kullanabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.