RecyclerView实践笔记 | 青训营笔记

129 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第3天。

RecyclerView简介

RecyclerView是一种滚动控件,属于AndroidX的新增控件 相比ListView,RecyclerView拥有更多的功能和更好的优化
比如说,RecyclerView可以轻易实现数据的横向滚动和瀑布流布局,这是ListView不能做到的。
这里以创建一个“相册App”作为例子来讲解

RecyclerView的使用

初步创建

在activity_main.xml中新增控件,代码如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

一个空白的RecyclerView控件就创建好了。

数据填充

RecyclerView并不能直接把数据转换称视图。
具体点,就是我们把数据和要生成的视图样式传给Adapter,当RecyclerView要填充里面的内容时Adapter就会创建ViewHolder并且将其和数据绑定到ViewHolder上。
那什么是ViewHolder? -> ViewHolder就是容纳View的容器
image.png

www.jianshu.com/p/99d72923c…

由上图可见,创建一个Adapter最主要的目标就是重写其三个方法, 并且创建一个符合需求的ViewHolder。
对于一个相册App,我们需要的子项样式应该是一个相册首图,加上相册名字。
建立一个新的xml,命名为layout_album.xml,这将是RecyclerView中的子项。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_margin="3dp"
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ImageView
        android:id="@+id/imgView"
        android:layout_width="match_parent"
        android:layout_gravity="center_horizontal"
        android:scaleType="centerCrop"
        android:layout_marginTop="3dp"
        android:layout_height="150dp"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:gravity="center_horizontal"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="-5dp"/>
</LinearLayout>

这里先创建一个Album类,作为数据的存放类

class Album(val id : Int, val name :String, val cover:String) {
    val photoList = ArrayList<String>()
}

创建Adapter类,与ViewHolde类

class MiniPhotoRecyclerAdapter(val albums : ArrayList<Album>) : RecyclerView.Adapter<MiniPhotoRecyclerAdapter.ViewHolder>(){
    inner class ViewHolder(view:View) : RecyclerView.ViewHolder(view){
        val AlbumImg = view.findViewById<ImageView>(R.id.imgView)
        val AlbumTitle = view.findViewById<TextView>(R.id.title)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_album,parent,false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.AlbumImg.setImageBitmap(BitmapFactory.decodeFile(albums[position].cover))
        holder.AlbumTitle.text=albums[position].name
        holder.itemView.setOnClickListener{
            val context = holder.itemView.context
            val intent = Intent(context,PhotoViewer::class.java)
            intent.putExtra("PHOTO",albums[position].photoLists)
            context.startActivity(intent)
        }
    }

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

在ViewHolder中存放子项的两个视图
在onCreateViewHolder中通过之前定义的xml文件创建子项的视图
在onBindViewHolder中设置子项的数据,设置事件。
getItemCount返回总共要创建几个子项。

使用

回到MainActiviy里,把RecyclerView绑定到代码上,并且把Adapter绑到RecyclerView上,再设置layoutManager

//Assuming that U can get the system album
val mAdapter = MiniPhotoRecyclerAdapter(Albums)
val recyclerView : RecyclerView = findViewById(R.id.recycle)
recyclerView.adapter = mAdapter
recyclerView.layoutManager = StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)

LayoutManager就是用来控制recyclerview的显示样式的。
在这里我用的是StaggeredGridLayoutManager,也就是瀑布流布局。第一个参数是设置一行有几个子视图,第二个参数设置了是竖着滚动还是横着滚动。
此外,还可以使用LinearLayoutManager,实现线性的布局,代码实现如下

val layoutManager = LinearLayoutManager(this)
/*
注:在设置横向布局的情况下
   要在子项的Layout文件里
   调整layout的宽度为固定值
*/
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
//当然也可以不设置,默认为垂直布局
recyclerView.layoutManager = layoutManager

LayoutManager默默的做了很多工作,包括测量,布局,滚动,创建子view。
对于不同的LayoutManager,也有不同的显示效果,都可以试试。

补充

做完了以上,就可以得到一个简单的相册app,这时候冒出来了一个新的需求
要有一个主相册摆在最顶上
做法很简单,加个ImageView而已
但当你这么做了,就会发现
诶,我在滚动下面的RecyclerView,上面的ImageView竟然还呆在原地?!

让其他元素跟着RecyclerView滚动

在主Activity的外层包裹上一层标签

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    >
    ................
    <!--Other codes.....-->
    </ScrollView>  

这时候你会发现,竟然出现了炫酷的吸顶效果,类似下图

image.png

摘自 Android 嵌套滑动总结

但我们要做的是一滑到底....
这时候只要在MainActivity加上一行代码

recyclerView.isNestedScrollingEnabled = false

手动关闭嵌套滑动即可

最终实现效果

Screenshot_2022-07-29-17-57-49-924_com.example.myalbumviewer.jpg.jpg