目录
1. 首先要用这个控件,你需要在gradle文件中添加包的引用
2. 创建一个主界面RecyclerViewActivity的布局文件recyclerview_main.xml
3. 主界面RecyclerViewActivity的逻辑代码
4. 把创建的主界面加入到androidmanifest.xml
一、什么是RecyclerView?
RecyclerView不仅可以实现和ListView同样的效果,还有优化了ListView中的各种不足。其可以实现数据纵向滚动,也可以实现横向滚动(ListView做不到横向滚动)。
RecyclerView是谷歌V7包下新增的控件,用来替代ListView的使用,在RecyclerView中,标准化了ViewHolder,类似于ListView中convertView用来做视图缓存。先来说说RecyclerView的亮点就是,他可以通过设置LayoutManager来快速实现listview、gridview、瀑布流的效果,而且还可以设置横向和纵向显示,添加动画效果也非常简单(自带了ItemAnimation,可以设置加载和移除时的动画,方便做出各种动态浏览的效果),
二、RecyclerView的适配器
由于RecyclerView可以上下或者左右滚动数据的,因此每滚动一次,view里面所现实的数据都会不一样,因此就需要适配器来决定该现实什么数据。
而RecyclerView是自己有自己的适配器模版(是一个抽象类)的。因此当我们自定义RecyclerView的适配器时,需要把继承RecyclerView的适配器模版(RecyclerView.Adapter),并重写其三个方法抽象方法。
这三个方法分别是:
onCreateViewHolder()用于创建ViewHolder实例,并把加载的布局传入到ViewHolder中,再把ViewHolder实例返回。 onBindViewHolder()用于对子项的数据进行赋值,会在每个子项(Item,即某一栏数据)被滚动到屏幕内时执行。 getItemCount()返回RecyclerView的子项数目(Item数目)。
即适配器每次其实都在配置一栏数据(一个Item)。
什么是ViewHolder?
ViewHolder类中各个成员都是一个个View。我们知道最终展示给用户看的界面看到的控件都是 一个个View,而在后台中,记录的一般都是数据,这些数据最终会在VIew中展示给用户。所以ViewHolder就相当于把数据转成纪录了数据的View的一个中间物体。ViewHolder都是通过VIew扽形式,记录着一栏数据(一个item),下面举个ViewHolder的例子:
三、RecyclerView的布局管理器
3.1 三大布局
在RecyclerView中提供了三种布局,第一是线性布局,第二是网格布局,第三是瀑布布局,而布局管理器LayoutManager则决定着到底选用哪一种布局。
如下图,作图是线性布局,跟LIstView一样,右图是列数为2的网格布局。
为了更好地展示网格布局和瀑布布局的区别,我把apple的字段复制了很多次,再运行,
如下图,左边是瀑布布局,右图是网格布局。可以看到瀑布布局上不会留白的。(两种的列数都为4)
3.2 横向、纵向划动
RecyclerView的滑动方向可以往左也可以往右,设置方式就在布局管理器中。
例如,在线性布局管理器LinearLayoutManager,在它的构造函数里,有RecycrView.VERTICAL 和 RecyclerView.HORIZONTAL ,分别表示这个布局是往纵向滑的和横向划的。
代码实例
1. 首先要用这个控件,你需要在gradle文件中添加包的引用
在app下的build.grade 下添加 RecycleView的 依赖:
implementation 'androidx.recyclerview:recyclerview:1.0.0'
2. 创建一个主界面RecyclerViewActivity的布局文件recyclerview_main.xml
<?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="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycleview"/>
</LinearLayout>
可以看到此界面的布局只有一个recyclerview控件
3. 主界面RecyclerViewActivity的逻辑代码
创建RecyclerViewActivity.kt (kotlin的类)
此界面为app启动的第一个页面。
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.*
import com.ugc.andorid.landing.adapter.MessageAdapter
import com.ugc.andorid.landing.view_class.MessagePic
class RecyclerViewActivity: AppCompatActivity() {
var messageList = mutableListOf<MessagePic>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.recyclerview_main)
//初始化要现实的数据
initMessages()
var recyclerView:RecyclerView = findViewById(R.id.recycleview)
//初始化布局管理器
var myLayoutManager:LinearLayoutManager = LinearLayoutManager(this) //线性布局
//var myLayoutManager:GridLayoutManager = GridLayoutManager(this,4) //网格 布局
//var myLayoutManager:StaggeredGridLayoutManager = StaggeredGridLayoutManager(4,OrientationHelper.VERTICAL) //瀑布布局
recyclerView.layoutManager = myLayoutManager
//创建适配器
var messageAdapter:MessageAdapter = MessageAdapter(this,messageList)
recyclerView.adapter = messageAdapter
}
/*初始化数据*/
fun initMessages(){
for(i in 1..20){
var apple:MessagePic = MessagePic("apple",R.drawable.apple_pic)
messageList.add(apple)
var banana:MessagePic = MessagePic("banana",R.drawable.banana_pic)
messageList.add(banana)
}
}
}
上面的代码中,初始化数据时,注意,我们是提前放了苹果的照片apple_pic.jpeg 和 香蕉的照片banana_pic.jpeg 进目录res/drawable中的。
4. 把创建的主界面加入到androidmanifest.xml
对主界面的布局和逻辑编写完成后,把该界面(即Activity)加入到Androidmanifest.xml中,相当于在系统中声明此Activity
在androidmanifest.xml中声明RecyclerViewActivity这个Activity
5.定义一栏数据显示的数据类型
MessagePic.kt:
这个类共有name和imageId两个类型。分别表示数据的名字和数据的图片的id。后续imageId会转成对应的图片,所以一栏数据展示的内容其实分别是 name和图片。
class MessagePic(var name:String, var imageId:Int) {
}
6. 定义一栏数据的布局
recycler_item.xml:
此布局表示,图片和名字信息会纵向地排列,即第一列数据为图片,第二列数据为name信息
<?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="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/message_name"
android:layout_gravity="center_vertical"
android:text="aaa"
android:layout_marginLeft="10dp"/>
</LinearLayout>
7. 编写RecyclerView控件的适配器
MessageAdapter.kt:
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.ugc.andorid.landing.R
import com.ugc.andorid.landing.view_class.MessagePic
class MessageAdapter:RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
private var datas:List<MessagePic>?=null
private var context:Context?=null
constructor(context:Context,datas:List<MessagePic>){
this.context = context
this.datas = datas
}
//定义ViewHolder
class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
var name:TextView = itemView.findViewById(R.id.message_name)
var image:ImageView = itemView.findViewById(R.id.message_image)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var view = LayoutInflater.from(context).inflate(R.layout.recycler_item,parent,false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return datas!!.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
var dataItem:MessagePic = datas!!.get(position)
holder.image.setImageResource(dataItem.imageId)
holder.name.setText(dataItem.name)
}
}
运行效果:(可以上下滑动)