Android Java实现RecyclerView多选item点击切换LinearLayout背景
RecyclerView多选切换Item背景实现方法
核心要解决两个问题:一是独立存储每个item的选中状态,避免RecyclerView复用导致状态错乱;二是点击时更新状态、局部刷新item,保证交互流畅。具体修改步骤如下:
前置准备
先准备好选中状态的LinearLayout背景资源,比如默认背景是你现有的@drawable/gradient,选中背景自行命名为gradient_selected放到drawable目录下即可。
代码修改
XML布局不需要改动,直接修改Adapter代码,新增状态存储、点击逻辑、状态绑定即可:
// 顶部补充需要导入的工具类 import android.util.SparseBooleanArray; import androidx.core.content.ContextCompat; import android.graphics.drawable.Drawable; import java.util.ArrayList; import java.util.List; public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { String[] adkr; String[] repeat; Animation anim; Context co; // 存储每个item的选中状态,key=item位置,value=是否选中,比HashMap内存占用更低 private final SparseBooleanArray selectedState = new SparseBooleanArray(); // 预加载两个状态的背景,避免每次绑定都重复读取资源 private final Drawable defaultBackground; private final Drawable selectedBackground; public MyAdapter(Context context, String[] all_adkars, String[] all_repeat) { co = context; adkr = all_adkars; repeat = all_repeat; // 初始化背景 defaultBackground = ContextCompat.getDrawable(co, R.drawable.gradient); selectedBackground = ContextCompat.getDrawable(co, R.drawable.gradient_selected); // 初始化所有item默认未选中 for (int i = 0; i < adkr.length; i++) { selectedState.put(i, false); } } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(co); View view = layoutInflater.inflate(R.layout.custom_list, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.textView.setText(adkr[position]); holder.repeat_Tv.setText(repeat[position]); // 核心:每次绑定item时,根据存储的状态设置对应背景,解决复用错乱问题 boolean isItemSelected = selectedState.get(position, false); holder.layout.setBackground(isItemSelected ? selectedBackground : defaultBackground); // 绑定点击事件,如果只想点击LinearLayout触发,把itemView换成holder.layout即可 holder.itemView.setOnClickListener(v -> { // 翻转当前item的选中状态 boolean newSelectState = !selectedState.get(position, false); selectedState.put(position, newSelectState); // 只刷新当前点击的item,比全量刷新性能好太多 notifyItemChanged(position); }); setAnimation(holder.itemView,position); } @Override public int getItemCount() { return adkr.length; } // 可选方法:需要获取所有选中item位置的时候直接调用 public List<Integer> getSelectedItemPositions() { List<Integer> selectedList = new ArrayList<>(); for (int i = 0; i < selectedState.size(); i++) { if (selectedState.valueAt(i)) { selectedList.add(selectedState.keyAt(i)); } } return selectedList; } public class MyViewHolder extends RecyclerView.ViewHolder { TextView textView, repeat_Tv; LinearLayout layout; public MyViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.textView); repeat_Tv = itemView.findViewById(R.id.repeat); layout = itemView.findViewById(R.id.ll_bg); } } private void setAnimation(View viewToAnimate, int position) { anim = AnimationUtils.loadAnimation(co, R.anim.list_anim); viewToAnimate.startAnimation(anim); } }
注意事项
- 绝对不要只在点击监听里直接修改layout的背景,不存状态的话,RecyclerView滑动复用ViewHolder的时候,选中状态会随机串到其他item上,必须在
onBindViewHolder里根据存储的状态统一设置UI。 - 用
notifyItemChanged(position)做局部刷新,不要每次点击都调用notifyDataSetChanged(),否则列表会卡顿,还会丢失item动画。 - 如果需要默认选中部分item,只要在Adapter初始化的时候往
selectedState里对应位置put true即可。
内容的提问来源于stack exchange,提问作者tareqbinhariz
相关产品推荐
相关产品推荐

