您的位置:首页 > 其它

RecyclerView嵌入CheckBox带来的显示问题的解决办法

2016-11-11 22:21 507 查看
android 的recyclerview(或者是listview)内部item的布局包含checkbox控件时,会遇到常见的问题:选择的checkbox后滑动listview内容时会checkbox选择的值会刷新成原来状态值(即没选中),选择listview所有checkbox值之后,只能获取当前可见的checkbox的值,向后滑动选择的值无法获取。就像下图所示,总共是有50条数据,开始的时候50条数据都没有选中,后面选中前5条数据,然后滑动列表,发现checkbox的选中状态会产生错位的现象。



我们先来看看开始的时候代码是如何写的:

MainActivity:

package com.example.yk.checkboxsingle;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<String> stringList;
public static Map<Integer,Boolean> map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView= (RecyclerView) findViewById(R.id.recycler);
stringList=new ArrayList<>();
map=new HashMap<>();
for (int i = 0; i < 50; i++) {
stringList.add("第"+i+"条数据");
}
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayout.HORIZONTAL,1,R.color.line));
MyAdapter adapter=new MyAdapter(stringList,this);
recyclerView.setAdapter(adapter);
}
}
MyAdapter:

package com.example.yk.checkboxsingle;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;

import java.util.List;

/**
* Created by yk on 2016/11/11.
*/
public  class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private List<String> data;
private Context context;
public MyAdapter(List<String> stringList,Context context) {
this.data=stringList;
this.context=context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(context).inflate(R.layout.item_layout,parent,false);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.checkBox.setTag(position);
holder.checkBox.setText(data.get(position));
}

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

public class ViewHolder extends RecyclerView.ViewHolder {
private CheckBox checkBox;
public ViewHolder(View itemView) {
super(itemView);
checkBox= (CheckBox) itemView.findViewById(R.id.cb_my);
}
}
}


解决以上问题可以采取以下思路:

重写Adapter的getView方法时,为每个checkbox添加事件响应并记录选择状态,通过获取获取状态记录值获取所有选择的checkbox值。

解决办法主要是在onBindViewHolder方法重处理:

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.checkBox.setText(data.get(position));
final Integer tag=new Integer(position);//初始化一个Integer实例,其值为position
holder.checkBox.setTag(tag);
if (MainActivity.map.containsKey(tag)){
holder.checkBox.setChecked(MainActivity.map.get(tag));
}else {
holder.checkBox.setChecked(false);//true or false 都可以,看实际需求
}
holder.checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (holder.checkBox.isChecked()){
MainActivity.map.put(tag,true);
}else {
MainActivity.map.put(tag,false);
}
}
});
}
效果如图:刚开始50条数据都没选中,后来选中前3条,滑动列表,并没有产生错位。



源码下载:点击打开链接//注明:链接里的源码有个地方写错了,应为:holder.checkBox.setChecked(MainActivity.map.get(tag));以博客里的为准。

在上面基础上拓展一个需求,也是我现在公司产品经理提出来的,解决方法和上面的类似,需求大致如图:



正常情况下每个item上显示的都是必要信息,有一些不重要的信息,但又不能缺少,这些信息需要通过点击item,然后让这些信息展示出来。如果照正常写法,发现会造成和checkbox类似的效果,会产生“错位”,明明点击了最前面的item,让点击了的item隐藏的信息展示出来了,当滑动到下方时,没有被点击的item隐藏的信息也会展示出来。是不是和我们的checkbox产生的错位类似呢,按照这种思路,最终解决了这个问题,见下方效果图:



主要代码:

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.checkBox.setText(data.get(position));
final Integer tag=new Integer(position);//初始化一个Integer实例,其值为position
holder.checkBox.setTag(tag);
holder.container.setTag(tag);
if (MainActivity.map.containsKey(tag)){
holder.checkBox.setChecked(MainActivity.map.get(tag));
}else {
holder.checkBox.setChecked(false);
}

if(MainActivity.isShown.containsKey(tag)){
holder.lin.setVisibility(MainActivity.isShown.get(tag)==View.VISIBLE ? View.VISIBLE:View.GONE);
}else {
holder.lin.setVisibility(View.GONE);
}
holder.checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (holder.checkBox.isChecked()){
MainActivity.map.put(tag,true);
}else {
MainActivity.map.put(tag,false);
}
}
});

holder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (holder.lin.isShown()){
holder.lin.setVisibility(View.GONE);
MainActivity.isShown.put(tag,View.GONE);
}else {
holder.lin.setVisibility(View.VISIBLE);
MainActivity.isShown.put(tag,View.VISIBLE);
}
}
});

}
item布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/ll_container"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">

<CheckBox
android:id="@+id/cb_my"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:button="@null"
android:drawableLeft="@drawable/check_box_style"
android:drawablePadding="5dp"
android:padding="5dp" />

<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:text="隐藏的信息"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>


参考文章:

1、Recycleview checkbox 复用出现混乱解决方法:http://blog.csdn.net/fangchao3652/article/details/44103945

2、完美解决ListView和CheckBox焦点冲突及复用时CheckBox错位等一系列问题:http://blog.csdn.net/zhangjinhuang/article/details/49561893

第二篇文章介绍了:解决ListView和CheckBox焦点冲突;CheckBox的选择、全选、反选、删除的实现;下拉刷新,上拉加载checkbox的选中错位等问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐