首先声明下,这是本人自己使用的做法,可能并不适合每个人,但是具有参考意义,分享给大家,不足的地方希望有人能提出来。
ListView在做应用的时候是经常被使用到的。一般开发应用程序的时候,我们会先做界面。这个时候,遇到ListView,我们会先模拟一些数据,而且,每个ListView通常都有类型的行为,比如,ListView的每个Item的点击效果,Item之间的横线,等等,而通常我们不会去使用自带的list item 的布局,而是自己去写一个布局,然后在自定义的Adapter中去inflate它。在多个地方都使用到这些特性,那么我们就可以把这些特性放到父类中来处理。而对于界面中共同的元素我们会放到style中去处理。
先看MainAdapter.java:
public class MainAdapter extends BaseCompatableAdapter<Map<String, String>> {
public MainAdapter(Context context, List<Map<String, String>> data) {
super(context, data);
}
class ViewHolder {
ImageView ivPic;
TextView tvName;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder viewHolder;
if (convertView == null) {
convertView = super.layoutInflater
.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.ivPic = (ImageView) convertView
.findViewById(R.id.iv_pic);
viewHolder.tvName = (TextView) convertView
.findViewById(R.id.tv_name);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
//TODO 接下去对数据进行绑定...
return convertView;
}
}
这里面做的事情非常简单,因为我把部分代码移到了父类BaseCompatableAdapter中,
下面看父类
BaseCompatableAdapter.java:
public abstract class BaseCompatableAdapter<T> extends BaseAdapter {
protected Context context;
private List<T> data;
protected LayoutInflater layoutInflater;
public BaseCompatableAdapter(Context context, List<T> data) {
this.context = context;
this.data = data;
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
if (data == null)
return 0;
return data.size();
}
@Override
public T getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}
覆写过BaseAdapter的同学应该可以知道,实际上就是把BaseAdapter的部分方法在这里面覆写了。以后你的其他的Adapter都继承自这个Adapter,那么可以省下不少的代码量。
最后看主界面:
MainActivity.java:
public class MainActivity extends Activity {
private ListView lvData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvData = (ListView)findViewById(R.id.lv_data);
List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();
Map<String, String> map;
for(int i = 0; i < 50; i++){//模拟数据量,当并没有加入真实的数据源
map = new HashMap<String, String>();
dataList.add(map);
}
lvData.setAdapter(new MainAdapter(this, dataList));
}
}
上面是关于代码中如何较为简洁的处理ListView和Adapter,下面则是设置ListView的界面
用一个style来设置每个ListView公用的地方,如下:
res/values/styles.xml:
<resources>
<style name="listview_style" parent="@android:style/Widget.ListView">
<!-- <item name="android:listSelector">@drawable/list_item_bg_selecter</item> -->
<item name="android:divider">@drawable/line</item><!-- @drawable/list_item_line -->
<item name="android:cacheColorHint">@null</item>
</style>
</resources>
这里面设置了divider,即Item之间的横线,cacheColor设置为null,listSelector设置list item点击下去的效果。因为我将selector写到了list item里面去了,所以这里就注释掉了,实际上这里最好可以写入一个默认的selector,这样所有的listview的item都默认有一个selector样式!在一些情况下,比如List item中嵌套着一个ViewStub,那么这个时候你设置的listSelector会失效,这个时候,只能够在List item中设置背景selector,而且要注意,如果是ViewStub这种情况的话,不能将list item最外层的layout设置背景selector,而是要在除了ViewStub,在剩下的那个控件里面设置selector,即点击会显示或隐藏ViewStub的那个控件。
你的listview可以这样引用style:
<ListView
android:id="@+id/lv_data"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
style="@style/listview_style"
/>
下面我们看看list Item
res/layout/list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/list_item_bg_selecter"
>
<ImageView
android:id="@+id/iv_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher"
android:layout_margin="5dip"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dip"
android:layout_toRightOf="@+id/iv_pic"
android:text="张三"
/>
</RelativeLayout>
注意在这里面我设置了android:background="@drawable/list_item_bg_selecter"这是关键,这里决定了ListView的每个Item的点击效果:但是这里也可以没有selector,如果没有的话,就会调用style中定义的selector,如果style中你没有设置,那么就会调用默认的selector(按下去橘黄色的那种效果)。
res/drawable/list_item_bg_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/list_item_bg_sel" android:state_pressed="true"/>
<item android:drawable="@drawable/list_item_bg_sel" android:state_focused="true"/>
<item android:drawable="@drawable/list_item_bg_sel" android:state_selected="true"/>
<item android:drawable="@drawable/list_item_bg_nor"/>
</selector>
这个selector中用到的图片可以是普通图片,也可以是自己画的图片,比如:
res/drawable/list_item_bg_sel.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#efece7" />
</shape>
list_item_bg_nor.xml也是一样,只不过设置不同的颜色。
当然横线你也可以自己画,比如:
res/drawable/line.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<stroke android:width="1dp" />
<size android:height="3dp" />
<solid android:color="#efece7" />
</shape>
下面附上效果图和项目结构图:
项目地址:
https://github.com/michaelye/ListViewStandardDemo