ListView算是我们平时经常使用到的一个工具了(当然现在有RecyclerView作为代替),之前一篇讲到ListView中的RecycleBin回收机制,这一篇先来大致讲一下ListView里面的一些用法吧。
ListView布局
在布局里面设置下ListView就可以了。对于ListView而言,里面的子view的布局只有一种,就是垂直布局。而在RecyclerView中对此进行了改进,支持了垂直,水平,瀑布型布局,还支持自定义布局,所以RecyclerView会更加强大一些。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/my_listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
ListView中的Adapter
Adapter算是ListView中一个比较重要的部分了,它实现的是一个适配器的功能,即ListView以及我们的数据源之间的耦合。这个在RecyclerView中也是一样的处理。Adapter是需要我们自己去实现的。在上一节中我们也提到过,其中最重要需要我们重写的方法就是getView()方法。一般我们在自定义Adapter的时候都是继承BaseAdapter这个类。
在ListView中,我们可以针对不同的数据采用不同的布局操作,这个我们在RecycleBin中也可以看到,在存储mScrapViews的时候可以看到,mScrapViews是一个ArrayList数据,不同类型的view会存储到数组相应的位置中(之前一直以为ListView中的view只有一种布局)。如果要实现多种布局的话,我们需要重写以下两个方法:
getViewTypeCount:返回view的类型的数量
getItemViewType(int position):获取该位置对应的view的类型
其中需要注意的一点,就是我们的view的类型值,不能超过view的类型的数量。即如果我们有两种类型,那么这两个类型设置的值应为0和1,不能超过2。这应该是我们在复用mScrapViews的时候,这个类型值会对应mScrapViews数组的下标。之前写的时候就是被这个地方给坑了...
在Adapter中,我们用viewHolder来对绑定listView的子view中的各个view控件,将其存储于listView的子view的tag中,下一次绘制的时候可以直接从tag中取出。
其他的就没啥了,贴下自己写的Adapter代码:
public class MyAdapter extends BaseAdapter {
private static final String TAG = "MyAdapter";
private Context mContext;
//data里面存储的是0-99数值
private List<String> data;
//总的view类型
private static int viewTypeCount = 2;
private static int viewTypeOne = 0;
private static int viewTypeTwo = 1;
//获取view类型数量
@Override
public int getViewTypeCount() {
return viewTypeCount;
}
//获取对应位置的类型
//这里定义凡是10的倍数的采用类型1,其他采用类型2
@Override
public int getItemViewType(int position) {
if(Integer.parseInt(data.get(position))%10 == 0)
return viewTypeOne;
else
return viewTypeTwo;
}
public MyAdapter(Context context, List<String> data){
this.mContext = context;
this.data = data;
}
//数据数量
@Override
public int getCount() {
return data.size();
}
//对应位置的内容
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
//获取该位置对应的view类型
int viewType = getItemViewType(position);
//如果为null,我们新生成一个view实例
//如果不为null,我们应该对其进行复用(节省资源)
if(convertView == null) {
vh = new ViewHolder();
if(viewType == viewTypeOne){
convertView = View.inflate(mContext,R.layout.my_view1, null);
//将viewHolder中对应的view控件初始化
vh.view1 = (TextView) convertView.findViewById(R.id.my_view_1);
}
else{
convertView = View.inflate(mContext,R.layout.my_view2, null);
vh.view2 = (TextView) convertView.findViewById(R.id.my_view_2);
vh.imageView = (ImageView) convertView.findViewById(R.id.my_image_view);
}
}
else {
vh = (ViewHolder) convertView.getTag();
}
//更新数据
if(viewType == viewTypeOne){
vh.view1.setText(data.get(position));
}
else {
vh.view2.setText(data.get(position));
vh.imageView.setImageResource(R.drawable.imgbg);
}
convertView.setTag(vh);
return convertView;
}
//viewHolder,用于存储所有view控件
class ViewHolder{
TextView view1;
TextView view2;
ImageView imageView;
}
}
两个对应的view布局:
my_view1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/my_view_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:gravity="center"
android:background="@color/colorYellow"
/>
</LinearLayout>
my_view2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/my_image_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_margin="5dp"
android:scaleType="centerInside" />
<TextView
android:id="@+id/my_view_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:gravity="center"
android:textSize="20dp"
/>
</LinearLayout>
</LinearLayout>
ListView的使用
在ListView的代码中,还定义了头部和底部,这两个是不同于ListView中的其他子view的,他们不会被回收到RecycleBin中。专门有两个List来对头部和尾部的view进行存储。RecyclerView中就没有这个功能了,需要我们自己去自定义。
Acrivity的代码如下:
public class ListViewActivity extends AppCompatActivity {
private ListView myListView;
private LayoutInflater inflater;
private View headView;
private View footView;
private List<String> data = null;
private MyAdapter adapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
inflater = LayoutInflater.from(this);
myListView = (ListView) findViewById(R.id.my_listview);
headView = (LinearLayout) inflater.inflate(R.layout.my_view_head,null);
footView = (LinearLayout) inflater.inflate(R.layout.my_view_foot,null);
//添加头部
myListView.addHeaderView(headView);
//添加尾部
myListView.addFooterView(footView);
initData();
adapter = new MyAdapter(this,data);
设置Adapter
myListView.setAdapter(adapter);
}
private void initData(){
data = new ArrayList<>();
for(int i = 0;i<100;i++){
data.add(Integer.toString(i));
}
}
}
最后出来的效果图大概是这样:
嗯,很丑...就这样吧。之后如果做了什么比较好看的,或者掌握了什么新的功能了再来更新....