ListView 和 RecyclerView 都是用于 Android 开发中列表展示时所用的常见控件。
1.使用前都需要准备适配器 Adapter :其实这两个控件的使用在初学者眼里之所以看起来复杂,最大的原因就是需要根据自己的业务来写一个Adapter类
2.使用前都需要准备 item 的 layout :除了准备一个适配器 Adapter 之外,还需要为列表中的每一项准备一个共用的 layout 。
3.使用时都是先初始化一个前面第一点提到的适配器Adapter,向其传入前面第二点提到的 layout 和所需要展示的数据集合等一些参数,然后将这个适配器通过 ListView.setAdapter(adapter) 方法,使适配器作为参数传入即可(RecyclerView在此之前还有一个步骤,后面会介绍到,只是一行代码的事,所以我认为使用时整体的步骤与 ListView 是基本相同的)。
4.关于使用步骤,Adapter 的不同实现,会出现传入参数上的差异,可能会导致部分人觉得这里使用时的相同点有点错误,其实我在这里只是想表达在使用时需要用到前面所提到的一些东西,具体的细微差别在使用时还是存在的,不用太纠结这部分。
1.首先,咱们先完成工作量最大的Adapter的编写。
public class MyTypeAdapter extends ArrayAdapter {
private int resourceId;
public MyTypeAdapter(Context context, int resourceId, List list){
super(context,textViewResourceId,list);
this.resourceId = resourceId;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
MyType myType = getItem(position);//这里的数据类型和你要展示的数据是一样的
View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
ImageView image = view.findViewById(R.id.image);
TextView text = view.findViewById(R.id.text);
image.setImageResource(myType.getImageId());
text.setText(myType.getText());
return view;
}
}
2.其次,完成 ListView 中每一项的共用 item_layout 。
3.最后。做完了准备工作,在需要使用 ListView 的布局文件中添加它。然后和使用其他控件一样,在 Activity 中获取,实例化Adapter,并将需要展示的数据集合传入。最后一步,将 Adapter 设置给 ListView ,大功告成。
4.如何开启点击事件
4.1 对整个 item 的点击事件,只需要对 ListView 增加事件监听即可,在 onItemClick 方法中, position 表示点击的 item 为第几项,一般通过这个下标进行对应的数据处理。
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//do something...
}
});
4.2 对 item 中某个控件的点击事件,则需要在 Adapter 中,在 getView 方法中获取绑定到控件之后,向其正常添加点击事件即可。同样的,getView 方法也有一个 position 参数,也是表示点击的 item 下标。
1.对 ListView 优化应该从哪里入手呢?想想我们对这个控件的使用准备,显然最先想到的应该是咱们编写的 Adapter 了。
2.通过新建一个内部类 ViewHolder 将子项的各个控件作为成员属性,重写 getView 方法。
3.对传入该方法的参数 convertView 进行判断,如果为 null 则进行布局和控件的加载,并将 viewHolder 通过 setTag 存储到 view 中,如果不为 null 则直接 view.getTag() 。
4.这个做法可以使控件和布局不必每次都被重复加载。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
viewHolder = new ViewHolder();
viewHolder.image = view.findViewById(R.id.image);
viewHolder.text = view.findViewById(R.id.text);
view.setTag(viewHolder);//将ViewHolder存储到View中
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
return view;
}
static class ViewHolder {
TextView text;
ImageView image;
}
上面讲的就是 ListView 的一些基本内容,还有许多东西需要去探索。接下来讲的关于 RecyclerView 其实也大同小异,只要理解了需要 Adapter 作为桥梁去连接数据和 ListView ,那其实 RecyclerView 的基本使用也和 ListView 没有很大区别。
1.使用前添加依赖
implementation 'com.android.support:recyclerview-v7:27.1.1'
Androidx的话是:
implementation 'androidx.recyclerview:recyclerview:1.1.0'
2.和 ListView 没两样,Adapter 先搞一个,让它继承 RecyclerView.Adapter<> 将其中的泛型指定为 adapter.ViewHolder 。
定义内部类继承 RecyclerView.ViewHolder 。传入的参数通常是 RecyclerView 子项的最外层布局。构造函数接受数据源。由于它继承于 RecyclerView.Adapter ,所以必须重写 onCreateViewHolder() , onBindViewHolder() 和 getItemCount() 三个方法。
第一个方法用于创建 ViewHolder 实例并把加载的布局传入构造函数并返回 holder ,第二个方法则是子项的控件进行绑定并对每个子项赋值,第三个方法返回 recylerview 的子项数目。
public class MyAdapter extends RecyclerView.Adapter {
private List mList;
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView mImage;
TextView mText;
public ViewHolder (View view) {
super(view);
mImage = (ImageView) view.findViewById(R.id.image);
mText = (TextView) view.findViewById(R.id.text);
}
}
public MyAdapter (List list){
mList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position){
MyType myType = mList.get(position);
holder.mImage.setImageResource(myType.getImageId());
holder.mText.setText(myType.getText());
}
@Override
public int getItemCount(){
return mList.size();
}
3.其次编写 item_layout ,这个和 ListView 没有任何区别,除非你需要一些其他的列表布局,不过这些都是细微的差别。
4.正式使用,和 ListView 的使用相似,获取 RecyclerView 后实例化适配器,传入一些必要的参数,然后 setAdapter ,但在 setAdapter 之前需要使用 LayoutManager 指定布局方式,这就是前面提到的一行代码的事(虽然看到是两行,但是硬要写成一行也不是不行)。LineatLayoutManager 指的是线性布局。
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
5.点击事件:对于整个子项的点击事件,在 viewHolder 中添加保存最外层 view ,在 onCreatViewHolder 中通过 holder.view.setOnClickListener 进行设置子项的点击事件;对于子项中的控件的点击事件,也同样在这里进行设置事件监听即可。
6.其他布局
RecyclerView 还可以实现横向滚动,只需要将子项的布局 item_layout 进行修改,即不要使宽度占满屏幕,其他根据需要调整,然后再使用时候设置 LayoutManager 时写
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
RecyclerView 还有 GridLayoutManager 和 StaggeredGridLayoutManager 。
GridLayoutManager layoutManager = new GridLayoutManager(this,5);
设置网格布局的代码如上,第二个参数是网格的列数。瀑布流也大同小异,网上查一下资料就行了。
1.ListView 的布局就是普通的列表展示,而 RecyclerView 可以横向滚动,还有瀑布流、表格之类的展示,可以适用于不同的业务需求
2.ListView 需要自行优化,自定义 ViewHolder 等一些内容
3.RecyclerView 还有一些其他的优点,但是我还没有研究过,所以就不多说了。如果只是用于展示一些简单的文字数据的话用 ListView 代码量应该会少一点。
1.其实这两个控件的使用都不是很复杂,只是相对于之前学习的其他控件而言,这两个控件就显得相对有些麻烦。
其实使用起来只需要和上面写的一样分四步来看,就很容易记住了。
第一步:在需要的地方添加 ListView \ RecyclerView ,这一步和其他控件没有区别
第二步:编写 Adapter ,把这一步做完基本就搞定百分之九十的工作了
第三步:编写 item_layout ,这个根据业务需求写即可
第四步:在 Activity \ Fragment 或其他使用 ListView 的地方绑定控件,实例化 Adapter 并传入数据,将该 Adapter 设置给 ListView 即可