IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 7.27-1 控件RecyclerView -> 正文阅读

[移动开发]Android 7.27-1 控件RecyclerView

1.RecyclerView的基本用法

与之前的控件都不同,RecyclerView(RV)属于新增控件,要想在之前版本能够使用,需要在build.gradle中加入RV库的依赖。
新建RecyclerViewTest项目,打开app/build.gradle文件,加入依赖如下:
在这里插入图片描述
然后写入布局,需要注意的是,因为RV并不是内置在系统SDK中的,所以需要写出完整的包路径(其实会自动补全的)。

<?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/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

随后,我们需要实现和ListView同样的页面,先把图片文件夹和Fruit类及fruit_item.xml也复制过来,把里面的button删掉。
在这里插入图片描述
接下来需要为RV准备一个适配器,新建FruitAdapter类继承自RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder,这个类型是我们自己定义的内部类。
代码如下:

class FruitAdapter(val fruitList: List<Fruit>):
    RecyclerView.Adapter<FruitAdapter.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_item, 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
    }

    override fun getItemCount(): Int {
        return fruitList.size
    }
}

ViewHolder
onCreateViewHolder()
onBindViewHolder()
getItemCount()
这是RV适配器的标准写法。首先定义一个内部类ViewHolder,它要继承自RV.ViewHolder,ViewHolder的著构造函数中要传入一个View参数,这个参数通常就是RV子项的最外层布局,这样就可以通过findViewById()方法来获取布局中的ImageView和TextView实例了。

FruitAdapter必须重写RV.Adapter的三个方法:
onCreateViewHolder()用于创建ViewHolder实例,将fruit_item布局加载进来,然后创建一个ViewHolder实例;并把加载出来的布局传入构造函数中,最后将ViewHolder的实例返回。
onBindViewHolder()用于对RV子项数据进行赋值,会在每个子项被滚动到屏幕内的时候执行,这里通过position参数的到当前项的Fruit实例,然后再将数据设置到ViewHolder的ImageView和TextView当中即可。
getItemCount()用于告诉RV一共有多少子项,直接返回数据源的长度就可以了。

适配器准备好了,就开始使用RV了,修改MainActivity中的代码:

    private val fruitList = ArrayList<Fruit>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initFruits()
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        val adapter = FruitAdapter(fruitList)
        recyclerView.adapter = adapter
    }

    private fun initFruits(){
        repeat(2){
            fruitList.apply {
                add(Fruit("Apple", R.drawable.apple_pic))
                add(Fruit("Banana", R.drawable.banana_pic))
                add(Fruit("Orange", R.drawable.orange_pic))
                add(Fruit("Watermelon", R.drawable.watermelon_pic))
                add(Fruit("Pear", R.drawable.pear_pic))
                add(Fruit("Grape", R.drawable.grape_pic))
                add(Fruit("Pineapple", R.drawable.pineapple_pic))
                add(Fruit("Strawberry", R.drawable.strawberry_pic))
                add(Fruit("Cherry", R.drawable.cherry_pic))
                add(Fruit("Mango", R.drawable.mango_pic))
            }
        }
    }

一样的,先初始化水果数据,然后在recyclerView中设置一个LinearLayoutManager的实例,指定RV的布局为线性布局,这样展现效果就和ListView一样了;其次将水果数据传给FruitAdapter的实例,并将其配置给recyclerView,这样就可以了。
运行结果:
在这里插入图片描述

2.横向滚动和瀑布流布局

2.1 横向滚动

现在尝试一下使用RV进行横向的滚动。
首先对fruit_item进行修改,因为现在的布局是水平排列的,不适合横向滚动,需要改成垂直排列比较合理。

<?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_marginTop="10dp"/>

    <TextView
        android:id="@+id/fruitName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"/>

</LinearLayout>

MainActivity增添一行代码,配置布局排列方式为horizontal

        val layoutManager = LinearLayoutManager(this)
        layoutManager.orientation = LinearLayoutManager.HORIZONTAL
        recyclerView.layoutManager = layoutManager

在这里插入图片描述

2.2 瀑布流布局

ListView的布局排列时由自身去管理的,而RV则将这个工作叫个了LayoutManager,它制定了一套可扩展的布局排列接口,子类要按照接口的规范来实现,就能制定出各种不同排列方式的布局了。除了LinearLayoutManager之外,RV还给我们提供了GridLayoutManager网络布局 和 StaggeredGridLayoutManager瀑布流布局 这两种内置的布局排列方式。

接下来试试瀑布流布局
修改fruit_item布局:

<?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_marginTop="10dp"/>

    <TextView
        android:id="@+id/fruitName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp"/>

</LinearLayout>

其实只改了一点点
然后修改MainActivity中的代码:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initFruits()
//        val layoutManager = LinearLayoutManager(this)
//        layoutManager.orientation = LinearLayoutManager.HORIZONTAL
//        recyclerView.layoutManager = layoutManager
        val layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
        recyclerView.layoutManager = layoutManager
        val adapter = FruitAdapter(fruitList)
        recyclerView.adapter = adapter
    }

    private fun initFruits(){
        repeat(2){
            fruitList.apply {
                add(Fruit(getRandomLengthString("Apple"), R.drawable.apple_pic))
                add(Fruit(getRandomLengthString("Banana"), R.drawable.banana_pic))
                add(Fruit(getRandomLengthString("Orange"), R.drawable.orange_pic))
                add(Fruit(getRandomLengthString("Watermelon"), R.drawable.watermelon_pic))
                add(Fruit(getRandomLengthString("Pear"), R.drawable.pear_pic))
                add(Fruit(getRandomLengthString("Grape"), R.drawable.grape_pic))
                add(Fruit(getRandomLengthString("Pineapple"), R.drawable.pineapple_pic))
                add(Fruit(getRandomLengthString("Strawberry"), R.drawable.strawberry_pic))
                add(Fruit(getRandomLengthString("Cherry"), R.drawable.cherry_pic))
                add(Fruit(getRandomLengthString("Mango"), R.drawable.mango_pic))
            }
        }
    }
    private fun getRandomLengthString(str: String): String{
        val n = (1..20).random()
        val builder = StringBuilder()
        repeat(n){
            builder.append(str)
        }
        return builder.toString()
    }

修改为在声明layoutManager时指定StaggeredGridLayoutManager,其构造函数有两个参数,第一个指定布局的列数,第二个指定布局的排列方向。由于瀑布流布局需要各个子项的高度不一致才能看出明显的效果,所以这里写了一个方法将TextView中的内容进行了随机的加长,使长度层次不齐。

运行结果:
在这里插入图片描述

3.RecyclerView的点击事件

不同于ListView,RV并没有提供方法去注册点击事件,我们需要自己给子项具体的View去注册点击事件。
修改FruitAdapter里的代码

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.fruit_item, parent, false)
        val viewHolder = ViewHolder(view)
        viewHolder.itemView.setOnClickListener{
            val position = viewHolder.adapterPosition
            val fruit = fruitList[position]
            Toast.makeText(parent.context, "You clicked view ${fruit.name}", Toast.LENGTH_SHORT).show()
        }
        viewHolder.fruitImage.setOnClickListener{
            val position = viewHolder.adapterPosition
            val fruit = fruitList[position]
            Toast.makeText(parent.context, "You clicked image ${fruit.name}", Toast.LENGTH_SHORT).show()
        }
        return viewHolder
    }

上述代码为最外层布局和ImageView都注册了点击事件,RV可以轻松实现子项中任意控件或布局的点击事件。现在两个点击事件中获取用户点击的position,通过position拿到相应的Fruit实例,分别弹出不同内容。

运行结果:
在这里插入图片描述
在这里插入图片描述
点击图片返回图片的点击结果,点击文字部分,由于TextView没有注册点击事件,因此点击文字是个事件会被子项的最外层布局捕获。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:56:17  更:2021-07-28 07:58:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 22:10:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码