【问题标题】:Get the position after filtering recyclerview过滤recyclerview后获取位置
【发布时间】:2019-01-12 22:44:20
【问题描述】:

我有一个 recyclerview 和一个搜索字段。 如果回收站未过滤,则单击打开所选项目的正确详细信息,但在过滤回收站后打开错误的详细信息。 适配器:

公共类 AllProductReyclerAdapter 扩展 RecyclerView.Adapter {

private BaseActivity mContext;
private OnClickItem mInterface;
private  List<Produse> dataList;

public AllProductReyclerAdapter(BaseActivity con, List<Produse> mainCat, OnClickItem _interface) {

    if(con!=null) {
        mContext = con;
        mInterface=_interface;
        dataList=mainCat;
    }
}

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

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_category_items, parent, false);
    ViewHolder vh = new ViewHolder(v);


    return vh;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {

    holder.tvCatMain.setText("Denumire :"+dataList.get(position).getDenumire());
    holder.tvCode.setText("Code :"+dataList.get(position).getCod());
    holder.tvDeposit.setText("Depozit :"+dataList.get(position).getDepozit());
    holder.tvCant.setText("Cant :"+dataList.get(position).getCant());
    holder.tvDate.setText(dataList.get(position).getPicture());
    if (dataList.get(position).getPicture()!=null)
        Picasso.get().load("http://mysite/test/img/"+dataList.get(position).getProcesare()+" "+dataList.get(position).getCuloare()+".jpg").into(holder.ivItem);

    if (dataList.get(position).getPicture()!=null)
        Picasso.get()
                .load("http://mysite/test/img/"+dataList.get(position).getProcesare()+" "+dataList.get(position).getCuloare()+".jpg")
                .placeholder(R.drawable.placeholder)
                .error(R.drawable.placeholder)
                .into(holder.ivItem);

      holder.linMain.setTag(dataList.get(holder.getAdapterPosition()));

    holder.linMain.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mInterface.onListItemClick(view.getId(),position);

        }
    });

}



public class ViewHolder extends RecyclerView.ViewHolder {
    public LinearLayout linMain;
    public ImageView ivItem;
    public TextView tvCatMain,tvCode,tvDeposit,tvCant,tvDate;

    public ViewHolder(View view) {
        super(view);

        tvCatMain = view.findViewById(R.id.tvCatMain);
        ivItem = view.findViewById(R.id.ivItem);
        tvCode = view.findViewById(R.id.tvCode);
        tvDeposit = view.findViewById(R.id.tvDeposit);
        tvCant = view.findViewById(R.id.tvCant);
        tvDate = view.findViewById(R.id.tvDate);
        linMain = view.findViewById(R.id.linMain);


    }
}

public void filterList(ArrayList<Produse> filterdNames) {
    this.dataList = filterdNames;
    notifyDataSetChanged();
}

}

这是片段:

公共类 DashboardFragment 扩展 BaseFragment {

private RecyclerView rlProductList;
private View ivFilter;
private AllProductReyclerAdapter adapter;
private List<Produse> list=new ArrayList<>();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_dashboard, container, false);
}

@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((MainActivity)getActivity()).setPageTitle("Produse in stoc");
    rlProductList = view.findViewById(R.id.rlProductList);
    ivFilter = view.findViewById(R.id.ivFilter);
    ivFilter.setOnClickListener(this);
    rlProductList.setLayoutManager(new LinearLayoutManager(baseActivity, LinearLayoutManager.VERTICAL, false));
    adapter= new AllProductReyclerAdapter(baseActivity,  list, new OnClickItem() {
        @Override
        public void onListItemClick(Object o, int position) {
            Gson gson = new Gson();
            String result = gson.toJson( list.get(position));
            Bundle bundle=new Bundle();
            bundle.putString("details",result);
            ProductdetailsFragment fragment=new ProductdetailsFragment();
            fragment.setArguments(bundle);
            displayView(fragment);
        }
    });
    rlProductList.setAdapter(adapter);

    if (getArguments()!=null){
        if (getArguments().getString("search")!=null){

            list.clear();
            list.addAll(Constants.filteredProduct);
            adapter.notifyDataSetChanged();
        }

    }else{
        list.clear();
        list.addAll(Constants.allProduct);
        adapter.notifyDataSetChanged();

    }
    EditText etFilter = view.findViewById(R.id.etFilter);
    etFilter.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            // TODO Auto-generated method stub


        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable s) {

            // TODO Auto-generated method stub
            if (adapter!=null){
                if (s.toString().length()>0)
                    filter(s.toString());
                else
                    adapter.notifyDataSetChanged();
            }
        }
    });
}

@Override
public void onClick(View view) {
    super.onClick(view);
    switch (view.getId()){
        case R.id.ivFilter:
            displayView(new ProductFilterFragment());
            break;

    }
}
private void filter(String names) {
    //new array list that will hold the filtered data
     ArrayList<Produse> filterdNames = new ArrayList<>();

    //looping through existing elements
    for (int i=0;i<list.size();i++) {
        //if the existing elements contains the search input
        if (list.get(i).getPicture()!=null&&list.get(i).getPicture().toLowerCase().contains(names.toLowerCase())) {
            //adding the element to filtered list
            filterdNames.add(list.get(i));
        }
    }

    //calling a method of the adapter class and passing the filtered list
    adapter.filterList(filterdNames);
}

}

【问题讨论】:

    标签: android filter android-recyclerview adapter


    【解决方案1】:

    我也遇到了这个问题,我找到的解决方案不是通过删除元素来过滤表格。但是过滤后的文章我将高度设置为0。这样我就保留了位置。

    代码在kotlin,如果你不能用java翻译,告诉我,我会帮你的。

    第 1 步:

    添加这个扩展(或用java方法翻译):

    var View.isRemovedHeight: Boolean
    get() {
        return this.height == 0
    }
    set(value) {
        if (value) {
            val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0)
            this.layoutParams = params
        } else {
            val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            this.layoutParams = params
        }
    }
    

    第 2 步: 将此添加到您的适配器中

    //Filtering implementation
    private var textFilter: String = ""
    private val filteredItems: ArrayList<Items> = ArrayList()
    

    还有这个:

    // Filtering implementation
    fun filter(text: String) {
        textFilter = text.toLowerCase()
    
        filteredCustomer.clear()
        filteredCustomer.addAll(items.filter { it.name.toLowerCase().contains(textFilter) || it.address.toLowerCase().contains(textFilter) || it.phone.toLowerCase().contains(textFilter) })
        notifyDataSetChanged()
    }
    
    fun notifyFilteringDataChanged() {
        filteredCustomer.addAll(items)
        filter(text = textFilter)
        notifyDataSetChanged()
    }
    

    第一种方法是逻辑过滤,第二种方法是刷新recycleriew。最好的办法是重写方法 notifyDataSetChanged 但我们不能,因为它是最终方法。所以我创建了一个自定义 notifyDataChanged

    第 3 步: 在layout xml中,在layout里面放一个id,因为我们会删除它的size,放到0

    //Filtering implementation
    val item = items[position]
    holder.container.isRemovedHeight = !filteredItems.contains(item)
    

    isRemovedHeight 是上面的扩展,但是对于java,你必须调用翻译的方法

    在您的活动中每当您想刷新回收视图中的数据时,请使用 notifyFilteringDataChanged() 方法,以便所有内容都是最新的,如下所示:

    adapter.notifyFilteringDataChanged()
    

    在你的éditent中调用这个方法:

    adapter.filter(s.toString())
    

    对不起我的英语,希望对你有帮助

    Java

    第 1 步:

    public boolean removeHeight(View view, boolean isRemoved) {
        if(isRemoved) {
            LayoutParams params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
            view.setLayoutParams(params);
        } else {
            LayoutParams params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            view.setLayoutParams(params);
        }
    
        return isRemoved;
    }
    

    第 2 步:

    private String textFilter = "";
    private ArrayList<Item> filteredItems = ArrayList();
    

    还有:

    public void filter(String text){
        textFilter = text.toLowerCase();
    
        filteredCustomer.clear();
        filteredCustomer.addAll(items.stream().filter(i -> i.name.toLowerCase().contains(textFilter)));
        notifyDataSetChanged();
    }
    
    public void notifyFilteringDataChanged(){
        filteredCustomer.addAll(items);
        filter(textFilter);
        notifyDataSetChanged();
    }
    

    第 3 步:

    Item item = items.get(position);
    removeHeight(holder.container, !filteredItems.contains(item));
    

    还有:

    adapter.notifyFilteringDataChanged();
    

    还有:

    adapter.filter(s.toString());
    

    【讨论】:

    • 感谢 Mickael 的回复。我试图翻译成Java,但我不知道如何制作。在第 1 步中,您在 Kotlin 中编写了一个扩展,如何在 Java 中进行此操作。
    • 看看我的编辑,我没有检查,但通常它应该可以工作,让我知道
    【解决方案2】:

    您不应该在 onBindViewHolder 方法中设置点击监听器。因为可能在数据集更改位置后捕获的值是错误的。 最佳做法是在 ViewHolder 中设置点击侦听器并使用 getAdapterPosition 获取位置。不要忘记将此值与 RecyclerView.No_Position 进行比较,如果不相等则调用您的回调。

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 1970-01-01
      • 2017-01-28
      • 2020-09-18
      • 2017-01-19
      • 1970-01-01
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多