简体   繁体   English

向我的 RecyclerView 添加过滤/搜索

[英]Adding filtering/search to my RecyclerView

I have a RecyclverView set up which works perfectly (it may not be the 'best practice' but it works)我有一个完美运行的 RecyclverView 设置(它可能不是“最佳实践”,但它有效)

The RecyclerView method I implemented was from this video我实现的 RecyclerView 方法来自这个视频

For this I did the below:为此,我做了以下事情:

  • I have added a RecyclerView in my activity_main.xml layout with an id @+id/recycler_view我在我的activity_main.xml布局中添加了一个 RecyclerView,其 ID 为@+id/recycler_view
  • Create a RecyclerView Adapter class called RecyclerViewAdapter创建一个名为RecyclerViewAdapter的 RecyclerView 适配器 class
  • Create a listitem layout called layout_listitem.xml创建一个名为layout_listitem.xml的列表项布局

This worked perfectly and pulls the information from a values xml called sheep.xml这完美地工作并从名为sheep.xmlvalues xml中提取信息

When you click on one of the items it loads activity GalleryActivity which presents the information from that item position in a new activity_gallery.xml layout.当您单击其中一个项目时,它会加载活动GalleryActivity ,该活动在新的activity_gallery.xml布局中显示来自该项目 position 的信息。

image examples below:下面的图像示例:

在此处输入图像描述

I want to add filtering/search to my RecyclerView.我想将过滤/搜索添加到我的 RecyclerView。 I have followed many guides online from various people and yet still can't get it to work.我在网上遵循了许多来自不同人的指南,但仍然无法让它发挥作用。 I created a menu layouts, set up a filterable method and a 'new list' to store the filtered results我创建了一个菜单布局,设置了一个可过滤的方法和一个“新列表”来存储过滤后的结果

Followed this this and this跟着这个这个这个

Can someone please help me point me in the right direction of a guide I can use with my current set up.有人可以帮我指出我可以在当前设置中使用的指南的正确方向吗? I am fairly primitive in my coding knowledge so please be kind.我的编码知识相当原始,所以请善待。

MainActivity主要活动

package com.british.sheep.breeds;

import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity{
    String[ ] url;
    String[ ] name;
    String[ ] type;
    String[ ] established;
    String[ ] handle;
    String[ ] colour;
    String[ ] fleece;
    String[ ] staple;
    String[ ] micron;
    String[ ] gallery;


    private static final String TAG = "MainActivity";
    //vars
    private ArrayList<String> mNames = new ArrayList<>();
    private ArrayList<String> mImageUrls = new ArrayList<>();
    private ArrayList<String> mTypes = new ArrayList<>();
    private ArrayList<String> mEstablisheds = new ArrayList<>();
    private ArrayList<String> mHandles = new ArrayList<>();
    private ArrayList<String> mColours = new ArrayList<>();
    private ArrayList<String> mFleeces = new ArrayList<>();
    private ArrayList<String> mStaples = new ArrayList<>();
    private ArrayList<String> mMicrons = new ArrayList<>();
    private ArrayList<String> mGalleryUrls = new ArrayList<>();



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Resources res = getResources();

        url = res.getStringArray( R.array.url ) ;
        name = res.getStringArray( R.array.name ) ;
        type = res.getStringArray( R.array.type ) ;
        established = res.getStringArray( R.array.established ) ;
        handle = res.getStringArray( R.array.handle ) ;
        colour = res.getStringArray( R.array.colour ) ;
        fleece = res.getStringArray( R.array.fleece ) ;
        staple = res.getStringArray( R.array.staple ) ;
        micron = res.getStringArray( R.array.micron ) ;
        gallery = res.getStringArray( R.array.gallery ) ;

        overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
        Log.d(TAG, "onCreate: started.");
        initImageBitmaps();
    }
    private void initImageBitmaps(){
        Log.d(TAG, "initImageBitmaps: preparing bitmaps.");
        for (int i = 0; i < url.length; i++) {
            mImageUrls.add(url[i]);
            mNames.add(name[i]);
            mTypes.add(type[i]);
            mEstablisheds.add(established[i]);
            mHandles.add(handle[i]);
            mColours.add(colour[i]);
            mFleeces.add(fleece[i]);
            mStaples.add(staple[i]);
            mMicrons.add(micron[i]);
            mGalleryUrls.add(gallery[i]);
        }
        initRecyclerView();
    }



    private void initRecyclerView(){
        Log.d(TAG, "initRecyclerView: init recyclerview.");
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, mNames, mImageUrls, mTypes, mEstablisheds, mHandles, mColours, mFleeces, mStaples, mMicrons, mGalleryUrls);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

}

RecyclerViewAdapter回收器视图适配器

package com.british.sheep.breeds;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private ArrayList<String> mImageNames = new ArrayList<>();
    private ArrayList<String> mImages = new ArrayList<>();
    private ArrayList<String> mImageTypes = new ArrayList<>();
    private ArrayList<String> mImageEstablisheds = new ArrayList<>();
    private ArrayList<String> mImageHandles = new ArrayList<>();
    private ArrayList<String> mImageColours = new ArrayList<>();
    private ArrayList<String> mImageFleeces = new ArrayList<>();
    private ArrayList<String> mImageStaples = new ArrayList<>();
    private ArrayList<String> mImageMicrons = new ArrayList<>();
    private ArrayList<String> mImageGallerys = new ArrayList<>();
    private Context mContext;

    public RecyclerViewAdapter(Context context, ArrayList<String> imageNames, ArrayList<String> images, ArrayList<String> types, ArrayList<String> establisheds, ArrayList<String> handles, ArrayList<String> colours, ArrayList<String> fleeces, ArrayList<String> staples, ArrayList<String> microns ,ArrayList<String> gallerys ) {
        mImageNames = imageNames;
        mImages = images;
        mImageTypes = types;
        mImageEstablisheds = establisheds;
        mImageHandles = handles;
        mImageColours = colours;
        mImageFleeces = fleeces;
        mImageStaples = staples;
        mImageMicrons = microns;
        mImageGallerys = gallerys;
        mContext = context;

    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {


        Glide.with(mContext)
                .asBitmap()
                .load(mImages.get(position))
                .into(holder.image);

        holder.imageName.setText(mImageNames.get(position));


        holder.parentLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                Intent intent = new Intent(mContext, GalleryActivity.class);
                intent.putExtra("image_url", mImages.get(position));
                intent.putExtra("image_name", mImageNames.get(position));
                intent.putExtra("image_type", mImageTypes.get(position));
                intent.putExtra("image_established", mImageEstablisheds.get(position));
                intent.putExtra("image_handle", mImageHandles.get(position));
                intent.putExtra("image_colour", mImageColours.get(position));
                intent.putExtra("image_fleece", mImageFleeces.get(position));
                intent.putExtra("image_staple", mImageStaples.get(position));
                intent.putExtra("image_micron", mImageMicrons.get(position));
                intent.putExtra("image_gallery", mImageGallerys.get(position));

                mContext.startActivity(intent);
            }
        });
    }

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

        public class ViewHolder extends RecyclerView.ViewHolder{

        ImageView image;
        TextView imageName;
        TextView imageType;
        TextView imageEstablished;
        TextView imageHandle;
        TextView imageColour;
        TextView imageFleece;
        TextView imageStaple;
        TextView imageMicron;
        ImageView imageGallery;
        RelativeLayout parentLayout;


        public ViewHolder(View itemView) {
            super(itemView);
            image = itemView.findViewById(R.id.image);
            imageName = itemView.findViewById(R.id.image_name);
            parentLayout = itemView.findViewById(R.id.parent_layout);
            imageType = itemView.findViewById(R.id.image_type);
            imageEstablished = itemView.findViewById(R.id.image_established);
            imageHandle = itemView.findViewById(R.id.image_handle);
            imageColour = itemView.findViewById(R.id.image_colour);
            imageFleece = itemView.findViewById(R.id.image_fleece);
            imageStaple = itemView.findViewById(R.id.image_staple);
            imageMicron = itemView.findViewById(R.id.image_micron);
            imageGallery = itemView.findViewById(R.id.image_gallery);

        }


        }



}

GalleryActivity图库活动

package com.british.sheep.breeds;

import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.bumptech.glide.Glide;

public class GalleryActivity extends AppCompatActivity {

    private static final String TAG = "GalleryActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gallery);
        overridePendingTransition(R.anim.mtrl_bottom_sheet_slide_in, R.anim.mtrl_bottom_sheet_slide_out);
        Log.d(TAG, "onCreate: started.");

        getIncomingIntent();
    }

    @Override
    public void onBackPressed() {
        finishMyActivity();
    }

    public void finishMyActivity() {
        finish();
        overridePendingTransition(R.anim.mtrl_bottom_sheet_slide_in, R.anim.mtrl_bottom_sheet_slide_out);
    }


    private void getIncomingIntent() {
        Log.d(TAG, "getIncomingIntent: checking for incoming intents.");

        if (getIntent().hasExtra("image_url") && getIntent().hasExtra("image_name") && getIntent().hasExtra("image_type") && getIntent().hasExtra("image_established") && getIntent().hasExtra("image_handle") && getIntent().hasExtra("image_colour") && getIntent().hasExtra("image_fleece") && getIntent().hasExtra("image_staple") && getIntent().hasExtra("image_micron") && getIntent().hasExtra("image_gallery")) {
            Log.d(TAG, "getIncomingIntent: found intent extras.");

            String imageUrl = getIntent().getStringExtra("image_url");
            String imageName = getIntent().getStringExtra("image_name");
            String imageType = getIntent().getStringExtra("image_type");
            String imageEstablished = getIntent().getStringExtra("image_established");
            String imageHandle = getIntent().getStringExtra("image_handle");
            String imageColour = getIntent().getStringExtra("image_colour");
            String imageFleece = getIntent().getStringExtra("image_fleece");
            String imageStaple = getIntent().getStringExtra("image_staple");
            String imageMicron = getIntent().getStringExtra("image_micron");
            String imageGallery = getIntent().getStringExtra("image_gallery");
            setImage(imageUrl, imageName, imageType, imageEstablished, imageHandle, imageColour, imageFleece, imageStaple, imageMicron, imageGallery);
        }
    }

    private void setImage(String imageUrl, String imageName, String imageType, String imageEstablished, String imageHandle, String imageColour, String imageFleece, String imageStaple, String imageMicron, String imageGallery) {
        Log.d(TAG, "setImage: setting te image and name to widgets.");

        //TextView name = findViewById(R.id.image_description);
        //name.setText(imageName);
        setTitle(imageName);

        TextView type = findViewById(R.id.image_type);
        type.setText(imageType);

        TextView established = findViewById(R.id.image_established);
        established.setText(imageEstablished);

        TextView handle = findViewById(R.id.image_handle);
        handle.setText(imageHandle);

        TextView colour = findViewById(R.id.image_colour);
        colour.setText(imageColour);

        TextView fleece = findViewById(R.id.image_fleece);
        fleece.setText(imageFleece);

        TextView staple = findViewById(R.id.image_staple);
        staple.setText(imageStaple);

        TextView micron = findViewById(R.id.image_micron);
        micron.setText(imageMicron);

        ImageView gallery = findViewById(R.id.image_gallery);
        Glide.with(this)
                .asBitmap()
                .load(imageGallery)
                .into(gallery);
    }


}

Here is an example, how you can implement a search filter on your RecyclerView.这是一个示例,如何在 RecyclerView 上实现搜索过滤器。 I am going to take mImageNames arrayList on which I'll perform the filter.我将使用mImageNames arrayList 来执行过滤器。 There are a couple of things we need to do.我们需要做几件事。

(Make a copy of list, Implement Filterable to your adapter class, write filter logic and return the filtered value to your MainActivity class) (复制一份列表,将Filterable实现到您的适配器 class,编写过滤器逻辑并将过滤后的值返回给您的 MainActivity 类)

public class RecyclerViewAdapter extends 
RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private ArrayList<String> mImageNames = new ArrayList<>();
private ArrayList<String> copyImageNames ;

public RecyclerViewAdapter (ArrayList<String> imageNames) {
mImageNames = imageNames;
copyImageNames = new ArrayList<>(imageNames);
} } 

After your implement Filterable you need to override this method inside your adapter class.实现Filterable后,您需要在适配器 class 中覆盖此方法。

@Override
public Filter getFilter() { return filter; }

After that we will write the logic to perform filter.I am considering that your mImageNames list has name of all the sheeps (Balwen,Beltex.....) so that you can filter by their names.之后,我们将编写执行过滤器的逻辑。我正在考虑您的mImageNames列表具有所有绵羊的名称(Balwen,Beltex .....),以便您可以按它们的名称进行过滤。

    Filter filter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        ArrayList<String> filteredList = new ArrayList<>();
        if (constraint == null || constraint.length() == 0) {
            filteredList.addAll(copyImageNames );
        } else {
            String filterPattern = constraint.toString().toLowerCase().trim();
            for (String s : copyImageNames ) {
                if (s.contains(filterPattern)) {
                    filteredList.add(s);
                }
            }
        }
        FilterResults results = new FilterResults();
        results.values = filteredList;
        return results;
    }
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        mImageNames .clear();
        mImageNames .addAll((List) results.values);
        notifyDataSetChanged();
    }
};

Adapter is done, now back to MainActivity Create a menu directory under res folder and save this xml code.适配器完成,现在回到 MainActivity 在 res 文件夹下创建一个菜单目录并保存这个 xml 代码。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_search"
    android:title="Search"
    app:actionViewClass="androidx.appcompat.widget.SearchView"
    app:showAsAction="always|collapseActionView" /></menu>

Now we will inflate the menu and appply the filter to your adapter.现在我们将扩展菜单并将过滤器应用于您的适配器。

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.my_menu, menu);
    MenuItem item =menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) item.getActionView();
    searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

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

First of all create in resources menu for your toolbar:首先在工具栏的资源菜单中创建:

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

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

    <item android:id="@+id/menu_item_search"
        android:title="@string/search"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/menu_setSort"
        android:icon="@drawable/ic_sort_off_24dp"
        android:title="@string/routes_sort"
        app:showAsAction="ifRoom" />

</menu>

add this line to one of items: app:actionViewClass="androidx.appcompat.widget.SearchView" then in your activity with RecyclerView:将此行添加到项目之一: app:actionViewClass="androidx.appcompat.widget.SearchView"然后在您的活动中使用 RecyclerView:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.your_menu, menu);
        MenuItem sortIcon = menu.findItem(R.id.menu_setSort);
        MenuItem searchItem = menu.findItem(R.id.menu_item_search);
        SearchView searchView = (SearchView) searchItem.getActionView();

        searchView.setOnQueryTextListener(this);
        return true;
    }

Do not forget to implement this interface to your Activivty - implements SearchView.OnQueryTextListener不要忘记为您的 Activivty 实现此接口 - implements SearchView.OnQueryTextListener

Because of this interface you implemetnt this methods:由于这个接口,你实现了这个方法:

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

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

You better make a class instead of all this ArrayLists:你最好制作一个 class 而不是所有这些 ArrayLists:

public class OneSheep {
    private String mFleeces ;
    private String mStaples ;
    private String mMicrons ;
    private String mGalleryUrls;
    private String mNames;
    private String mImageUrls ;
    private String mTypes;
    private String mEstablishedsist;
    private String mHandles ;
    private String mColours ;

    public OneSheep(String names, String imageUrls, String types, String establishedsist, String handles, String colours, String fleeces, String staples, String microns, String galleryUrls) {
        mNames = names;
        mImageUrls = imageUrls;
        mTypes = types;
        mEstablishedsist = establishedsist;
        mHandles = handles;
        mColours = colours;
        mFleeces = fleeces;
        mStaples = staples;
        mMicrons = microns;
        mGalleryUrls = galleryUrls;
    }

    public String getNames() {
        return mNames;
    }

    public String getImageUrls() {
        return mImageUrls;
    }

    public String getTypes() {
        return mTypes;
    }

    public String getEstablishedsist() {
        return mEstablishedsist;
    }

    public String getHandles() {
        return mHandles;
    }

    public String getColours() {
        return mColours;
    }

    public String getFleeces() {
        return mFleeces;
    }


    public String getStaples() {
        return mStaples;
    }

    public String getMicrons() {
        return mMicrons;
    }

    public String getGalleryUrls() {
        return mGalleryUrls;
    }
}

In your Activity make only one ArrayList<OneSheep> mSheeps , pass it to your RecaclerView Adapter and this way it is gonna be mach easier to maintain that code.在您的 Activity 中只制作一个ArrayList<OneSheep> mSheeps ,将其传递给您的 RecaclerView 适配器,这样维护该代码将变得更加容易。 Make your RecyclerView global for MainActivity, call it for example recyclerView and your searchResult() method will look somethink like that:使您的 RecyclerView 全局用于 MainActivity,例如调用它 recyclerView 并且您的searchResult()方法看起来像这样:

private void searchResult(String query) {
        ArrayList<OneSheep> newSheepsList = new ArrayList<>();
        for (OneSheep sheep:mSheeps) {
            if (sheep.getNames().contains(query)){
                newSheepsList.add(sheep);
                break;
            }
            if (sheep.getTypes().contains(query)){
                newSheepsList.add(sheep);
                break;
            }
            //add any conditions here
        }
        RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, newSheepsList);
        recyclerView.setAdapter(adapter);
    }

Hope this helps希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM