这是我参与「第四届青训营 」笔记创作活动的的第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的容器
由上图可见,创建一个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>
这时候你会发现,竟然出现了炫酷的吸顶效果,类似下图
但我们要做的是一滑到底....
这时候只要在MainActivity加上一行代码
recyclerView.isNestedScrollingEnabled = false
手动关闭嵌套滑动即可