当前位置: 移动技术网 > 移动技术>移动开发>Android > RecyclerView三种常用效果的实现方法-android-kotlin

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

2020年07月23日  | 移动技术网移动技术  | 我要评论

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有一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能实现不同排列方式的布局

效果如下(水果图源:《第一行代码》第三版)

横向滚动效果实现

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

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

<?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
        //·······略·······
    }
}

效果如下

瀑布流效果实现

先修改子项的布局文件

<?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的构造方法接受两个参数
第一个参数表示列数
第二个参数表示布局的排列方式,我们这里设置了垂直排列

效果如下

添加点击事件

修改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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网