欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

RecyclerView三种常用效果的实现方法-android-kotlin

程序员文章站 2022-03-27 21:48:09
RecyclerView相对于ListView拥有更高的性能和扩展性不过如果理解了ListView的性能优化,就能对RecyclerView有更深刻的认识有关ListView的优化,可阅读上一篇博文《ListView的创建和优化》...

RecyclerView相对于ListView拥有更高的性能和扩展性
不过如果理解了ListView的性能优化,就能对RecyclerView有更深刻的认识
有关ListView的优化,可阅读上一篇博文《ListView的创建和优化》

基本使用方法(纵向滚动)

由于RecyclerView是新增控件,在使用之前需要在app/build.gradle文件中添加其依赖

dependencies {
    //·······略·······
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
}

然后我们修改布局文件,为其添加一个RecyclerView控件

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

由于RecyclerView并没有内置在系统SDK中,所以需要写出完整的包路径

接着我们为其创建一个适配器

//创建一个适配器,其继承于RecyclerView.Adapter,泛型指定为FruiAdapter.ViewHolder(需要自定义的内部类)
class FruitAdapter(val fruitList:List<Fruit>): RecyclerView.Adapter<FruitAdapter.ViewHolder>() {

    //用于缓存控件实例的内部类ViewHolder
    inner class ViewHolder(view:View):RecyclerView.ViewHolder(view){
        val fruitImage:ImageView = view.findViewById(R.id.fruitImage)
        val fruitName:TextView = view.findViewById(R.id.fruitName)
    }

    //重写父类的三个方法
    //创建并自动缓存布局
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_layout,parent,false)
        return ViewHolder(view)
    }
    //当子项进入屏幕时调用,对子项进行赋值
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        //获取当前项的元素
        val fruit = fruitList[position]
        //将元素的值赋给当前子项的各个控件
        holder.fruitImage.setImageResource(fruit.imageId)
        holder.fruitName.text = fruit.name
    }
    //告诉RecyclerView有多少个子项,直接返回列表大小即可
    override fun getItemCount(): Int {
        return fruitList.size
    }
}

最后修改MainActivity,开始使用RecyclerView

class MainActivity : AppCompatActivity() {
    //数据源
    private val fruitList = ArrayList<Fruit>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //初始化数据列表
        initfruit()
        //用于指定RecyclerView的布局方式(相对于ListView的巨大优势)
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        //设置适配器
        val adapter = FruitAdapter(fruitList)
        recyclerView.adapter = adapter
    }
    private fun initfruit(){
        repeat(2){
            fruitList.add(Fruit("Apple",R.drawable.apple_pic))
            fruitList.add(Fruit("Banana",R.drawable.banana_pic))
            fruitList.add(Fruit("Orange",R.drawable.orange_pic))
            fruitList.add(Fruit("Watermelon",R.drawable.watermelon_pic))
            fruitList.add(Fruit("Pear",R.drawable.pear_pic))
            fruitList.add(Fruit("Grape",R.drawable.grape_pic))
            fruitList.add(Fruit("Pineapple",R.drawable.pineapple_pic))
            fruitList.add(Fruit("Strawberry",R.drawable.strawberry_pic))
        }
    }
}

ListView的布局排列是由自身去管理的,而RecyclerView则将这个工作交给了LayoutManager.
LayoutManager有一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能实现不同排列方式的布局

效果如下(水果图源:《第一行代码》第三版)
RecyclerView三种常用效果的实现方法-android-kotlin

横向滚动效果实现

由纵向滚动变为横向滚动十分的简单

首先我们要改变子项布局元素的排列方式为垂直

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="80dp"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/fruitImage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp" />
    <TextView
        android:id="@+id/fruitName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp"/>
</LinearLayout>

然后在MainActivity中调用LinearLayoutManagersetOrientation()方法来设置布局的排列方式,只需要添加一行代码即可

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //·······略·······
        val layoutManager = LinearLayoutManager(this)
        //添加下面这行代码来表明布局排列方式为水平
        layoutManager.orientation = LinearLayoutManager.HORIZONTAL
        recyclerView.layoutManager = layoutManager
        //·······略·······
    }
}

效果如下
RecyclerView三种常用效果的实现方法-android-kotlin

瀑布流效果实现

先修改子项的布局文件

<?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/fruitImage"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp" />
    <TextView
        android:id="@+id/fruitName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginLeft="10dp"/>
</LinearLayout>

由于瀑布流布局的宽度应该是根据列数来自动适配的,因此LinearLayout的宽度应改为match_parent。
使用layout_margin来让子项之间留一点间距
TextView改为左对齐,比较美观

最后,只需要修改MainActivityonCreate()方法中的一行代码即可

class MainActivity : AppCompatActivity() {
        //·······略·······
        //将StaggeredGridLayoutManager实例设置到RecyclerView
        val layoutManager = StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)

        recyclerView.layoutManager = layoutManager
        //·······略·······
}

StaggeredGridLayoutManager的构造方法接受两个参数
第一个参数表示列数
第二个参数表示布局的排列方式,我们这里设置了垂直排列

效果如下
RecyclerView三种常用效果的实现方法-android-kotlin

添加点击事件

修改FruitAdapter类中的onCreateViewHolder()方法

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_layout,parent,false)
    val viewHolder = ViewHolder(view)
    //为最外层布局设置点击事件
    viewHolder.itemView.setOnClickListener{
        //获取用户点击的position
        val position = viewHolder.adapterPosition
        //获取position处的数据列表元素
        val fruit = fruitList[position]
        //使用Toast展示
        Toast.makeText(parent.context,"Click ${fruit.name}",Toast.LENGTH_SHORT).show()
    }
    return viewHolder
}

上述中itemView代表最外层布局,也可以将其改为任意布局中的控件(比如fruitImage)
RecyclerView的强大之处也在于此,它可以实现任意子项中任意控件或者布局的点击事件

本文地址:https://blog.csdn.net/qq_15989473/article/details/107524416