【问题标题】:How to move item to the last position when Checkbox is checked? (RecyclerView, ViewHolder)选中复选框时如何将项目移动到最后一个位置? (RecyclerView, ViewHolder)
【发布时间】:2018-12-17 18:25:11
【问题描述】:

我尝试制作一个包含复选框的 RecyclerView(如果已经购买了某些东西)。我想将项目移动到 CheckBox 检查更改的最后一个位置并将背景设置为绿色。我试图从 ArrayList 中删除项目,然后再次添加它,但它只适用于字符串名称,它不保持状态(复选框状态或颜色)。其他时候它会抛出异常:当 RecyclerView 正在计算布局或滚动时,无法调用此方法。谁能告诉我我做错了什么?

对不起我的英语。

import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> 
{
private ArrayList<String> mDataset;
private ArrayList<FinalListItem> finalListItems;
public MyAdapter(ArrayList<String> mDataset) {
this.mDataset = mDataset;
[enter image description here][1]finalListItems = new ArrayList<>();
    for (String a : mDataset) {
        finalListItems.add(new FinalListItem(a, false));
    }
}
@Override
public long getItemId(int position) {
    return position;
}
@Override
public int getItemViewType(int position) {
    return position;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
    holder.final_list_TextView1.setText(finalListItems.get(position).getName());
    if(finalListItems.get(position).isChecked){
        holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
    }
    else{
        holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
    }
    holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            FinalListItem finalItem = new FinalListItem(finalListItems.get(position).getName(),true);
            if (isChecked) {
                holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
                finalListItems.remove(finalListItems.get(position));
                finalListItems.add(finalItem);
                notifyDataSetChanged(); //weird behaviour of app
            } else {
                holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
            }

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

private class FinalListItem {
    private String name;
    private boolean isChecked;

    public FinalListItem(String name, boolean isChecked) {
        this.name = name;
        this.isChecked = isChecked;
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean isChecked) {
        this.isChecked = isChecked;
    }

    public String getName() {
        return name;
    }
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    final public TextView final_list_TextView1;
    final public CheckBox checkBox;
    final public LinearLayout linearLayout;

    public MyViewHolder(View view) {
        super(view);
        final_list_TextView1 = (TextView) view.findViewById(R.id.final_list_TextView1);
        checkBox = (CheckBox) view.findViewById(R.id.checkBox1);
        linearLayout = (LinearLayout) view.findViewById(R.id.linearLayout1);
    }
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.finallist_list_layout, parent, false);
    return new MyViewHolder(view);
}

}

【问题讨论】:

    标签: java android android-recyclerview android-styles


    【解决方案1】:

    您应该更改代码的主要内容是仅更改数据然后让适配器根据更改的数据显示列表是很重要的。这意味着,你不应该改变例如自己的背景,但您应该更改 FinalListItem 的列表并通知适配器。

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        holder.final_list_TextView1.setText(finalListItems.get(position).getName());
    
        // remove the Listener before setting the checked state programmatically
        // and set all the attributes (checked state and background color) here
        holder.checkBox.setOnCheckedChangeListener(null);
        if(finalListItems.get(position).isChecked){
            holder.linearLayout.setBackgroundColor(Color.rgb(0, 225, 0));
            holder.checkBox.setChecked(true);
        }
        else{
            holder.linearLayout.setBackgroundColor(Color.rgb(255, 255, 255));
            holder.checkBox.setChecked(false);
        }
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // Lint warning : don't use "final int position"
                int currentPosition = holder.getAdapterPosition();
                if (isChecked) {
                    FinalListItem finalItemBefore = finalListItems.get(currentPosition);
                    FinalListItem finalItemAfter = new FinalListItem(finalItemBefore.getName(),true);
                    finalListItems.remove(finalItemBefore);
                    finalListItems.add(finalItemAfter);
                    notifyDataSetChanged();
                } else {
                    finalListItems.get(currentPosition).setChecked(false);
                    // no need to update the whole list since only one item has changed
                    notifyItemChanged(currentPosition);
                }
            }
        });
    }
    

    另请注意,从getItemViewType() 返回位置 不是一个好主意。通过这样做,您告诉运行时每个View 都是唯一的,并且回收Views 是不可能的,这将不利于RecyclerView 的性能。

    您的列表的实现方式,一个View 类型就足够了,因此您根本不需要重写该方法,因为这是默认实现:

    @Override
    public int getItemViewType(int position) {
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      @0X0nosugar 答案是正确的:),我发现我们也可以使用

      notifyItemRemoved(currentposition); //after removing an item
      notifyItemInserted(currentposition); //after inserting an item
      

      它为我们的适配器提供了漂亮流畅的动画。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-21
        • 2011-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多