Android ListView相关知识

来源:互联网 发布:最悲惨的人生 知乎 编辑:程序博客网 时间:2024/05/22 13:33
这是平常自己总结的一些与ListView相关的问题,虽然现在都用RecyclerView了,但是公司的项目用的还是ListView,而且平常写东西时总是习惯用ListView,所以还是决定贴出来了

1.ListView的优化策略
  • 使用convertView
  • 使用ViewHolder
  • 滑动不加载
  • 异步加载图片
  • 局部刷新item

2.局部刷新 
  • 有的列表可能notifyDataSetChanged()代价有点高,最好能局部刷新。
  • 局部刷新的重点是,找到要更新的那项的View,然后再根据业务逻辑更新数据即可。

private void refreshData(int position) {         // 得到可见的第一个item的位置         int visibleItem = list.getFirstVisiblePosition();          // TODO: 这里应该是只有要刷新的item在显示时才会进行刷新              if (position - visibleItem < 0 ) {             return;        }         View view = list.getChildAt(position);         TextView tv = (TextView) view.findViewById(R.id.txt);         tv.setText("我是局部刷新的view!!!");         // TODO:更新mDatas中的数据        mDatas.get(position).setName("我是局部刷新的view!!!");     }

解释

首先只有当要局部刷新的item是当前可见的item时才有必要进行刷新(利用firstViewsible和visibleCount判断),然后可以直接得到要刷新的item的view,然后进行改变。

要注意的是改变数据源时无论是否可见是都需要改变的。

3. 解决listview的item内的组件抢占焦点的问题
当点击一个item时若item中有button等组件时可能会会抢占焦点,所以可以通过下面两种方法解决
  • 给button设置如下属性
    android:focusable = "false"    android:clickable = "true"
  • 在item的布局文件的根节点中添加下面的属性
    android:descendantFocusability="blocksDescendants"


4.找到listview的item里的组件并设置监听器

一种方法是在适配器中的getView()方法中找到该组件然后设置监听器,但是因为在适配器中所以onClick()方法中不可能有什么操作,比如说我想点击某个button让当前页面跳转到另一个页面,那么这在adapter中是无法实现的。所以可以在adapter中写一个监听器接口,当onClick的时候调用接口中的方法,而我们只需让有该listview的fragment或activity实现该接口重写该方法即可

5. ClipPadding
这个不多说,ListView的ClipPadding设为false,就能为ListView设置各种padding而不会出现丑陋的滑动“禁区”了。

6.ListView多选框错位问题
当listview的item中包含CheckBox时,如果不保存选中状态那么因为复用convertview的缘故会导致CheckBox每次都恢复原状。解决办法是在实体类中添加isChecked属性,当选中时就记录状态,然后在getview方法中设置前再判断一下。

实体类

public class People {        public String name;        public int age;        public boolean isChecked;            public People(String name, int age, boolean isChecked) {            this.name = name;            this.age = age;            this.isChecked = isChecked;        }    }

适配器
        
class MyAdapter extends BaseAdapter implements             CompoundButton.OnCheckedChangeListener{                @Override            public int getCount() {                return list.size();            }                @Override            public Object getItem(int position) {                return list.get(position);            }                @Override            public long getItemId(int position) {                return position;            }                @Override            public View getView(int position, View convertView, ViewGroup parent) {                ViewHolder holder;                if (convertView == null) {                    convertView = View.inflate(SecondActivity.this, R.layout.item, null);                    holder = new ViewHolder();                    holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);                    holder.name = (TextView) convertView.findViewById(R.id.name);                    holder.age = (TextView) convertView.findViewById(R.id.age);                    convertView.setTag(holder);                } else {                    holder = (ViewHolder) convertView.getTag();                }                // 设置tag来记录checkbox的位置                holder.checkbox.setTag(position);                holder.checkbox.setOnCheckedChangeListener(this);                holder.name.setText(list.get(position).name);                holder.age.setText(list.get(position).age+"");                holder.checkbox.setChecked(list.get(position).isChecked);                return convertView;            }                @Override            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                if (isChecked) {                    list.get((int)buttonView.getTag()).isChecked = true;                } else {                    list.get((int)buttonView.getTag()).isChecked = false;                }            }        }            class ViewHolder {            CheckBox checkbox;            TextView name;            TextView age;        }    }


7. ListView 多Item布局
通过在实体类中添加type字段然后在getView方法中进行判断来解析不同的convertView。  

每个布局都要复用所以要多重写两个方法,一个是
    
    getViewTypeCount()  用来返回不同的布局数    getItemViewType(int position) 用来返回position位置的item类型

sample


    
public class MyAdapter extends BaseAdapter{     private List<Entity> mList;     private Context mContext;     public MyAdapter(List<Entity> list, Context context) {             mList = list;             mContext = context;     }       @Override       public int getCount() {            return mList.size();       }       @Override       public Object getItem(int position) {           return mList.get(position);       }       @Override       public long getItemId(int position) {          return position;       }       @Override       public int getViewTypeCount() {          return 2;       }      @Override       public int getItemViewType(int position) {          int type = mList.get(position).itemType;          Log.e("getItemViewType", "position: " + position + ", type:" + type);          return type;       }       @Override       public View getView(int position, View convertView, ViewGroup parent) {         int type = mList.get(position).itemType;         ViewHolderTitle viewHolderTitle;         ViewHolderContent viewHolderContent;         if (convertView == null) {             if (type == 0) {                convertView = View.inflate(mContext, R.layout.item_title, null);                 viewHolderTitle = new ViewHolderTitle();                   viewHolderTitle.title = (TextView) convertView.findViewById(R.id.title);                   convertView.setTag(viewHolderTitle);            } else if (type == 1) {                   convertView = View.inflate(mContext, R.layout.item_content, null);                   viewHolderContent = new ViewHolderContent();                   viewHolderContent.content = (TextView) convertView.findViewById(R.id.content);                   convertView.setTag(viewHolderContent);            }        }        if (type == 0) {            viewHolderTitle = (ViewHolderTitle) convertView.getTag();            viewHolderTitle.title.setText(mList.get(position).title);        } else if (type == 1) {            viewHolderContent = (ViewHolderContent) convertView.getTag();            viewHolderContent.content.setText(mList.get(position).title);        }        return convertView;    }     class ViewHolderTitle {         TextView title;     }     class ViewHolderContent{         TextView content;     }


8. ListView 的item的高度

item的高度是根据item中最大的那个控件来确定的,在根viewgrouop中设置layout_height的高度不会起作用,但设置minHeight便可以

一个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="match_parent"        android:minHeight="80dp"  // 这里即可设置item的高度        android:gravity="center_vertical"        android:background="@color/colorPrimary"        >            <ImageView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:src="@mipmap/ic_launcher"            android:layout_marginLeft="10dp"            />        <TextView            android:id="@+id/content"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="内容"            android:layout_marginLeft="30dp"            android:textSize="22sp"            android:textColor="@color/colorAccent"            />    </LinearLayout>


不知道有没有会看啊~  还有代码格式怎么这么难调嘞... 明天又是周一了,周末都没有好好看书学习!




   

0 0
原创粉丝点击