赞
踩
目录
本篇文章主要讲解滚动控件RecyclerView的使用,包括基本使用和点击事件。
上篇文章主要讲解了ListView的用法,但是ListView并不是完全没有缺点的,如:不使用技巧优化,性能会很差;还有,扩展性也不够好,它只能实现数据纵向滚动的效果。
为此RecyclerView不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足,且Android官方也更加推荐使用RecyclerView。
RecyclerView属于新增控件,被定义在了support库中,想要使用,需要在项目的build.gradle中添加相应的依赖库。
首先新建RecyclerView项目,并创建好活动。
打开app/build.gradle,在dependencies闭包中添加如下代码:
implementation 'androidx.recyclerview:recyclerview:1.2.1'
添加完后点击Sync Now来同步。
然后修改activity_main.xml中的代码如下:
- <?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">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </LinearLayout>
接下来实现与前一文章的ListView相同的效果,直接将Image类、item.xml、image3.png复制过来(如有需要参考代码,请参考上一文章,链接:https://blog.csdn.net/Tir_zhang/article/details/129718771?spm=1001.2014.3001.5501)。
接下来为RecyclerView准备一个适配器,新建一个adapter类,代码如下:
代码稍微有点长,但是比ListView适配器更好理解。
首先定义一个内部类ViewHolder,继承自RecyclerView.ViewHolder,然后在构造函数中传入View参数,这个参数通常是RecyclerView子项的最外层布局,然后可以通过findViewById()方法来获取到布局中的ImageView和TextView实例了。
adapter的构造函数,用于把展示的数据源传进来。
adapter继承自RecyclerView.Adapter,需要重写onCreateViewHolder()、onBindViewHolder()、getItemCount()这3个方法。onCreateViewHolder()方法是用于创建ViewHolder实例的;onBindViewHolder()方法用于对RecyclerView子项数据赋值,会在子项被滚动到屏幕内的时候执行,通过position参数获取到当前项的实例,再设置到ImageView和TextView当中;getItemCount()方法用于告诉RecyclerView一共有多少子项,直接返回长度。
- public class adapter extends RecyclerView.Adapter<adapter.ViewHolder> {
- private List<Image> list;
- static class ViewHolder extends RecyclerView.ViewHolder{
- ImageView image;
- TextView name;
- public ViewHolder(View view){
- super(view);
- image = (ImageView) view.findViewById(R.id.image);
- name = (TextView) view.findViewById(R.id.name);
- }
- }
-
- public adapter(List<Image> list2){
- list = list2;
- }
-
- public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
- View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
- ViewHolder holder = new ViewHolder(view);
- return holder;
- }
-
- public void onBindViewHolder(ViewHolder holder,int position){
- Image image = list.get(position);
- holder.image.setImageResource(image.getImageId());
- holder.name.setText(image.getName());
- }
-
- public int getItemCount(){
- return list.size();
- }
- }
准备好适配器,可以使用RecyclerView了,修改MainActivity中的代码,如下:
下面的LayoutManager用于指定RecyclerView的布局方式,这里使用的LinearLayoutManager是线性布局的意思。
- public class MainActivity extends AppCompatActivity {
- private List<Image> list = new ArrayList<>();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- init();//初始化数据
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
- LinearLayoutManager layoutManager = new LinearLayoutManager(this);
- recyclerView.setLayoutManager(layoutManager);
- adapter ad = new adapter(list);
- recyclerView.setAdapter(ad);
- }
- private void init(){
- for(int i = 0; i < 2; i++){
- Image a = new Image("A",R.drawable.image3);
- list.add(a);
- Image b = new Image("B",R.drawable.image3);
- list.add(b);
- Image c = new Image("C",R.drawable.image3);
- list.add(c);
- Image d = new Image("D",R.drawable.image3);
- list.add(d);
- Image e = new Image("E",R.drawable.image3);
- list.add(e);
- }
- }
- }
效果如下:
首先修改item.xml布局的代码,如下:
目前此布局的元素都是水平排列,适用于纵向滚动的场景,如果横向滚动,应该改成垂直排列。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="100dp"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"/>
-
- <TextView
- android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="10dp"/>
-
- </LinearLayout>
接下来修改MainActivity代码,如下:
只加入了一行代码: layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
默认是纵向排列,调用setOrientation()方法来设置布局排列方向。
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- init();//初始化数据
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
- LinearLayoutManager layoutManager = new LinearLayoutManager(this);
-
- layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
-
- recyclerView.setLayoutManager(layoutManager);
- adapter ad = new adapter(list);
- recyclerView.setAdapter(ad);
- }
效果如下:
除LinearLayoutManager之外,还有GridLayoutManager和StaggeredGridLayoutManager这两种内置的布局方式。GridLayoutManager用来实现网格布局,StaggeredGridLayoutManager用来实现瀑布流布局,下面实现瀑布流布局。
修改item.xml代码,如下:
这里只修改了两部分,首先将LinearLayout的宽度由100dp改成了match_parent,因为瀑布流的宽度应该是根据布局的列数自动适配,而不是固定值;另外,TextView的对齐方式改成了左对齐。
- <?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="wrap_content"
- android:layout_margin="5dp">
-
- <ImageView
- android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"/>
-
- <TextView
- android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:layout_marginTop="10dp"/>
-
- </LinearLayout>
接着修改MainActivity.java代码,如下:
首先,再onCreate方法中,创建StaggeredGridLayoutManager实例,构造函数接收两个参数,第一个参数用于指定布局的列数,第二个参数用于指定布局的排列方向。
- public class MainActivity extends AppCompatActivity {
- private List<Image> list = new ArrayList<>();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- init();//初始化数据
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
-
- StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
-
- recyclerView.setLayoutManager(layoutManager);
- adapter ad = new adapter(list);
- recyclerView.setAdapter(ad);
- }
- private void init(){
- for(int i = 0; i < 5; i++){
- Image a = new Image("AAAAAAAAAAAAAAAAAA",R.drawable.image3);
- list.add(a);
- Image b = new Image("BBBBBB",R.drawable.image3);
- list.add(b);
- Image c = new Image("CCCCCCCCCCC",R.drawable.image3);
- list.add(c);
- Image d = new Image("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",R.drawable.image3);
- list.add(d);
- Image e = new Image("EEE",R.drawable.image3);
- list.add(e);
- }
- }
- }
效果如下:
RecyclerView的点击事件需要我们自己给子项具体的View去注册点击事件,比ListView实现要复杂一点。
那么为什么RecyclerView设计的更复杂一点?假设以下场景:如果想要点击子项里具体的按钮,如何做?ListView的setOnItemClickListener()方法注册的是子项的点击事件,实现这个功能比较麻烦,为此,RecyclerView直接去除了子项点击事件的监听器,所有的点击事件都有具体的View去注册。
接下来尝试实现。
修改adapter中的代码,如下:
下面加粗部分为新增代码。
imageView变量用来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件,这里为ImageView注册了点击事件。
public class adapter extends RecyclerView.Adapter<adapter.ViewHolder> { private List<Image> list; static class ViewHolder extends RecyclerView.ViewHolder{ View imageView; ImageView image; TextView name; public ViewHolder(View view){ super(view); imageView = view; image = (ImageView) view.findViewById(R.id.image); name = (TextView) view.findViewById(R.id.name); } } public adapter(List<Image> list2){ list = list2; } public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false); final ViewHolder holder = new ViewHolder(view); holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int position = holder.getAbsoluteAdapterPosition(); Image image = list.get(position); Toast.makeText(view.getContext(), "你点击了"+image.getName(), Toast.LENGTH_SHORT).show(); } }); return holder; }...
}
效果如下:
希望本文章对你有帮助,如果你对Android开发感兴趣,请持续关注本专栏,帮助你从入门到项目实战,你将收获:Android基础开发、各种经典功能实现、项目实战、开发自己的APP、将APP上传应用商店、靠广告赚钱等等,持续更新ing......
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。