zoukankan      html  css  js  c++  java
  • android listview 使用checkbox问题

          在android中使用listview时需要了解listview加载数据的原理,为了避免listview由于列表项过多每次需要进行new造成性能低下的问题,android中的listview使用了控件复用从而避免了每次进行new控件的问题。

    @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view;
                ViewHolder viewHolder = null;
                if(convertView==null)
                {
                    viewHolder = new ViewHolder();
                    view = getLayoutInflater().inflate(R.layout.list_item, null);
                    viewHolder.btn = (Button)view.findViewById(R.id.buttonid);
                    viewHolder.textView = (TextView)view.findViewById(R.id.textid);
                    viewHolder.radioBtn = (CheckBox)view.findViewById(R.id.radioid);
                    view.setTag(viewHolder);
                }
                else
                {
                    view = convertView;
                    viewHolder = (ViewHolder)view.getTag();
                }

    自定义adapter时重写getView方法时只有当converView为空时才需要创建控件,只需要创建屏幕上刚好可以放下的那几条控件即可。

    在listview item上使用checkbox等空间时需要注意的问题是,checkbox选中的状态会错乱,如选中了第一条数据当滚动列表时该选中的状态可能会跑到其他条目上去,这个问题就是listview复用造成的。

    目前该问题的解决我是通过,将选中的checkbox id放入hashmap中,

    Map<Integer, Boolean> isCheckMap =  new HashMap<Integer, Boolean>();

    当滚动listview时判断该条目位置是否在这个hashmap中,如果在表示之前选中了,如果不在表示未选中将checkbox状态设为false。

    //找到需要选中的条目
    if(isCheckMap!=null && isCheckMap.containsKey(position))
      {
         viewHolder.checkBtn.setChecked(isCheckMap.get(position));
      }
    else
      {
         viewHolder.checkBtn.setChecked(false);
      }

    为了获取到checkbox的选中事件,还需要实现checkbox的setOnCheckedChangeListener

        viewHolder.checkBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        int radiaoId = Integer.parseInt(buttonView.getTag().toString());
                        if(isChecked)
                        {
                            //将选中的放入hashmap中
                            isCheckMap.put(radiaoId, isChecked);
                        }
                        else
                        {
                            //取消选中的则剔除
                            isCheckMap.remove(radiaoId);
                        }
                    }
                });

    另外需要注意的一个问题是,由于列表项布局文件使用了checkbox,Button等控件,如果不做设置的话这些控件的监听事件会优先于listview的setOnItemClickListener事件响应,所以即使listview实现了这个监听,在点击item的时候也捕获不到事件。解决办法如下:

    <?xml version="1.0" encoding="utf-8"?>
     <!--  android:descendantFocusability="blocksDescendants"表示覆盖子空间获取焦点,解决itemclick无效的问题-->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"
        android:orientation="horizontal" >
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >
           <ImageView
            android:id="@+id/imageid"
           style="@style/baseLayout"
           android:layout_alignParentLeft="true"
            android:background="@drawable/sym_keyboard_delete"
            />
    
        <TextView
            android:id="@+id/textid"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="10dp"
            android:layout_toLeftOf="@+id/radioid"
            android:text="sdfa" />
    
        <CheckBox
            style="@style/baseLayout"
            android:id="@+id/radioid"
            android:layout_height="50dp"
             android:layout_toLeftOf="@+id/buttonid"
            />
        
        <Button
            style="@style/baseLayout"
            android:layout_height="50dp"
            android:id="@+id/buttonid"
            android:layout_alignParentRight="true"
            android:background="@drawable/sym_keyboard_done"
            />
        </RelativeLayout>
        
       
    </LinearLayout>

    在listview item布局页面的根位置添加android:descendantFocusability="blocksDescendants" 表示覆盖子控件获取焦点,解决itemclick无效的问题。

    完整的代码如下:

    Activity类

    package com.example.sf;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import android.annotation.SuppressLint;
    import android.os.Handler;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AbsListView;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.CheckBox;
    import android.widget.CompoundButton;
    import android.widget.ListView;
    import android.widget.RadioButton;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class listViewActivity extends BaseActivity{
        private ListView listView;
        private List<HashMap<String, Object>> listData;
        private Handler handler = null;
        Map<Integer, Boolean> isCheckMap =  new HashMap<Integer, Boolean>();
        final List<HashMap<String, Integer>> isCheckList = new ArrayList<HashMap<String, Integer>>();
        @Override
        public int getContentViewId() {
            return R.layout.list_main;
        }
        @Override
        public void init() {
            handler = new Handler();
            listView = (ListView)findViewById(R.id.listid);
            listData = getData();
            listView.setAdapter(new myAdapter());
            listView.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view, int scrollState) {
                    Log.e("scrollState",scrollState+"");
                }
                @Override
                public void onScroll(AbsListView view, int firstVisibleItem,
                        int visibleItemCount, int totalItemCount) {
                            if(firstVisibleItem+visibleItemCount<totalItemCount)//判断是否需要加载数据
                            {
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        handler.postDelayed(new Runnable() {
                                            @Override
                                            public void run() {
                                            }
                                        },10);
                                    }
                                }).start();
                            }
                }
            });
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
                    Toast.makeText(getApplicationContext(), view.getTag()+"", Toast.LENGTH_SHORT).show();
                }
            });
        }
    
        /**
         * 数据封装
         * @return
         */
        private List<HashMap<String, Object>> getData()
        {
             List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
            for(int i=0;i<20;i++)
            {
                HashMap<String, Object> map = new HashMap<String, Object>();
                map.put("radioid", i);
                map.put("textview", "本元素的上边缘"+i);
                list.add(map);
            }
            return list;
        }
        
        /**
         * 自定义Adapter
         * @author Administrator
         *
         */
        public class myAdapter extends BaseAdapter
        {
            @Override
            public int getCount() {
                return listData.size();
            }
    
            @Override
            public Object getItem(int position) {
                return listData.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view;
                ViewHolder viewHolder = null;
                if(convertView==null)
                {
                    viewHolder = new ViewHolder();
                    view = getLayoutInflater().inflate(R.layout.list_item, null);
                    viewHolder.btn = (Button)view.findViewById(R.id.buttonid);
                    viewHolder.textView = (TextView)view.findViewById(R.id.textid);
                    viewHolder.checkBtn = (CheckBox)view.findViewById(R.id.radioid);
                    view.setTag(viewHolder);
                }
                else
                {
                    view = convertView;
                    viewHolder = (ViewHolder)view.getTag();
                }
                viewHolder.textView.setText(listData.get(position).get("textview").toString());
                viewHolder.checkBtn.setTag(listData.get(position).get("radioid").toString());
                //找到需要选中的条目
                if(isCheckMap!=null && isCheckMap.containsKey(position))
                {
                    viewHolder.checkBtn.setChecked(isCheckMap.get(position));
                }
                else
                {
                    viewHolder.checkBtn.setChecked(false);
                }
                viewHolder.btn.setTag(listData.get(position).get("radioid").toString());
                viewHolder.btn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(getApplicationContext(), "点击了"+v.getTag(), Toast.LENGTH_LONG).show();
                    }
                });
                viewHolder.checkBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        int radiaoId = Integer.parseInt(buttonView.getTag().toString());
                        if(isChecked)
                        {
                            //将选中的放入hashmap中
                            isCheckMap.put(radiaoId, isChecked);
                        }
                        else
                        {
                            //取消选中的则剔除
                            isCheckMap.remove(radiaoId);
                        }
                    }
                });
                return view; 
            }
            
        }
        public class ViewHolder
        {
            private TextView textView;
            private CheckBox checkBtn;
            private Button btn;
        }
    }
    View Code

    listview item布局文件

    <?xml version="1.0" encoding="utf-8"?>
     <!--  android:descendantFocusability="blocksDescendants"表示覆盖子空间获取焦点,解决itemclick无效的问题-->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"
        android:orientation="horizontal" >
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >
           <ImageView
            android:id="@+id/imageid"
           style="@style/baseLayout"
           android:layout_alignParentLeft="true"
            android:background="@drawable/sym_keyboard_delete"
            />
    
        <TextView
            android:id="@+id/textid"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="10dp"
            android:layout_toLeftOf="@+id/radioid"
            android:text="sdfa" />
    
        <CheckBox
            style="@style/baseLayout"
            android:id="@+id/radioid"
            android:layout_height="50dp"
             android:layout_toLeftOf="@+id/buttonid"
            />
        
        <Button
            style="@style/baseLayout"
            android:layout_height="50dp"
            android:id="@+id/buttonid"
            android:layout_alignParentRight="true"
            android:background="@drawable/sym_keyboard_done"
            />
        </RelativeLayout>
        
       
    </LinearLayout>
    View Code

    源码下载位置:

    http://download.csdn.net/detail/linchengbiao123/7133959

  • 相关阅读:
    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)转
    转载 获取管理员权限
    Linux端图形处理工具ImageMagick在Centos上的安装
    JQUERY 的AJAX只执行一次问题
    ASP.NET项目常见错误信息:HRESULT:0x800736B1
    存储过程(我们简称SP)的编写和优化
    sql server中扩展存储过程大全
    Range对象基本操作应用示例(2)
    让IIS支持DZ和PW的伪静态方法
    js日期时间函数(经典+完善+实用)
  • 原文地址:https://www.cnblogs.com/cnblogs-lin/p/3640023.html
Copyright © 2011-2022 走看看