android开发-自定义listView-(以及由于自身编写错误导致的bug修复)
前言
近期的项目里需要用listView去显示用户列表,自带的功能不足以满足我的设计需求,于是我就各方面学习了一下怎么制作一个自定义listView。并且也在开发过程中自己写错了代码因此特意记录引以为戒。
特别提示:下方演示代码仅适配我的设计需求,并且只摘录了核心代码,使用时需要根据自身需求做出适当改变。
核心代码块1 - MyListAdapter
class MyListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<MyOwnerFaceListInfo> beans;
public MyListAdapter() {
;
}
public MyListAdapter(Context mContext) {
this.mContext = mContext;
}
public MyListAdapter(ArrayList<MyOwnerFaceListInfo> beans, Context mContext) {
this.beans = beans;
this.mContext = mContext;
}
@Override
public int getCount() {
if(beans == null) {
return 0;
}
return beans.size();
}
@Override
public Object getItem(int position) {
return beans.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(beans == null) {
return null;
}
ViewHolder vh = null;
if (convertView == null ) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
vh = new ViewHolder();
vh.tv1=(TextView)convertView.findViewById(R.id.list_textView1);
vh.tv2=(TextView)convertView.findViewById(R.id.list_textView2);
vh.iv1=(ImageView)convertView.findViewById(R.id.list_imageView1);
// String userID = beans.get(position).Name;
// String userDate = beans.get(position).Date;
//
// vh.tv1.setText(userID);
// if(beans.get(position).FaceBitmap != null)
// vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
// vh.tv2.setText(userDate);
convertView.setTag(vh);
}else {
vh = (ViewHolder)convertView.getTag();
}
String userID = beans.get(position).Name;
String userDate = beans.get(position).Date;
vh.tv1.setText(userID);
vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
vh.tv2.setText(userDate);
// 绑定数据
//viewHolder.textView.setText(listData.get(position));
return convertView;
}
public static class ViewHolder{
TextView tv1;
TextView tv2;
ImageView iv1;
}
}
概述-以及bug代码
这部分代码里类MyOwnerFaceListInfo为我自定义的类,用于存放每个item所需的元素,基本如下:
class MyOwnerFaceListInfo {
public Bitmap FaceBitmap = null;
public String Name = null;
public String Date = null;
//------------------------
public MyOwnerFaceListInfo(String name,Bitmap faceBitmap){
Name = name;
FaceBitmap = faceBitmap;
}
}
上述代码中其他部分不需要在意,重点在于getView函数里的内容,里面用了ViewHolder这个机制节约了内存和使用时间,并且这部分我之前写错误了,我将数据初始化写在了视图初始化的部分里,也就是我上方代码注释的那一部分,导致了我显示时出现了超出屏幕范围的item数据加载错误的情况。
bug区域原始写法
if (convertView == null ) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
vh = new ViewHolder();
vh.tv1=(TextView)convertView.findViewById(R.id.list_textView1);
vh.tv2=(TextView)convertView.findViewById(R.id.list_textView2);
vh.iv1=(ImageView)convertView.findViewById(R.id.list_imageView1);
String userID = beans.get(position).Name;
String userDate = beans.get(position).Date;
vh.tv1.setText(userID);
if(beans.get(position).FaceBitmap != null)
vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
vh.tv2.setText(userDate);
}
这是由于采用了ViewHolder时,系统仅会对屏幕上显示的item做初始化和数据绑定,而超出屏幕范围的item采用的方法是继承移出屏幕的数据存放空间也就是继承convertView,而每一个item将显示时都会执行getView进行初始化,我的编写错误导致需要被加载的部分数据不能被初始化,因此出现了移出屏幕和移入屏幕的item数据错误的现象
引以为戒
核心代码块2 - list_bean_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#FFF"
android:gravity="center"
>
<ImageView
android:layout_margin="10dp"
android:id="@+id/list_imageView1"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@android:drawable/ic_menu_my_calendar"
android:background="#000"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
>
<TextView
android:id="@+id/list_textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="35dp"
android:text="abababababa"
android:layout_margin="5dp"
android:textColor="#000"
/>
<TextView
android:id="@+id/list_textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="tip:ababababa"
android:textSize="25dp"
android:layout_marginLeft="20dp"
android:textColor="#444"
/>
</LinearLayout>
</LinearLayout>
概述
这部分是自定义item,通过自定义要显示的list的元素的布局实现自身的设计。
对应绑定的代码为:
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
如果有自身的特殊设计需求,可以设计多个不同的布局,让每一行显示不同的设计
应用
//获取布局里的控件
mListView = (ListView) findViewById(R.id.dialog_list);
//初始化list适配器
myListAdapterOwner = new MyListAdapter(myOwnerList,context);
//为listView绑定适配器
mListView.setAdapter(myListAdapterOwner);
概述
使用是核心代码就这么3句。
其中决定显示内容的最后一句,因此如果想让list根据情况使用不同的数据模式,也可以通过自定义不同的适配器模型,然后通过绑定适配器的方式来决定显示内容。
自定义的适配器里的数据需要在绑定前完成初始化,也就是如果后续修改了list数据,如果想要这部分数据在listView里生效,则需要重新.setAdapter
结语
我的代码库里缺少一个自定义listView的模板,目前也补上了,以上代码已经切实证明可行,后续开发可以以此作为借鉴。
自定义ListView实践
本文介绍了一个自定义ListView的实现过程,包括如何创建适配器、ViewHolder模式的应用以及常见bug的解决方法。通过示例代码展示了如何正确绑定数据,避免因初始化错误导致的显示异常。
5250

被折叠的 条评论
为什么被折叠?



