基本用法
build.gradle引入
implementation 'androidx.recyclerview:recyclerview:1.1.0'
新建 Fruit 类
class Fruit(val name:String,val imageId:Int)
新建 item_fruit 布局
<?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="60dp">
<ImageView
android:id="@+id/fruitImage"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/fruitName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"/>
</LinearLayout>
新建FruitAdapter
class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHoler>() {
inner class ViewHoler(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): ViewHoler {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_fruit,parent,false)
return ViewHoler(view)
}
override fun getItemCount(): Int = fruitList.size
override fun onBindViewHolder(holder: ViewHoler, position: Int) {
val fruit = fruitList[position]
holder.fruitImage.setImageResource(fruit.imageId)
holder.fruitName.setText(fruit.name)
}
}
MainActivity
class MainActivity :AppCompatActivity() {
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(3){
fruitList.add(Fruit("Apple",R.drawable.apple))
fruitList.add(Fruit("Banana",R.drawable.banana))
fruitList.add(Fruit("Orange",R.drawable.orange))
fruitList.add(Fruit("Watermelon",R.drawable.watermelon))
}
}
}
横向滚动
修改一下 item_fruit 布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<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_marginTop="10dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
MainActivity 中
class MainActivity :AppCompatActivity() {
private val fruitList = ArrayList<Fruit>()
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 adapter = FruitAdapter(fruitList)
recyclerView.adapter = adapter
}
......
}
瀑布流
除了 LinearLayoutManager ,RecylerView 还提供了 GridLayoutManager(网格布局) 和 StaggeredGridLayoutManager(瀑布流布局)这两种内置的布局排列方式
实现瀑布流先修改下布局
<?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="wrap_content"
android:orientation="vertical"
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_marginTop="10dp"
android:layout_gravity="left"/>
</LinearLayout>
MainActivity
class MainActivity : AppCompatActivity() {
private val fruitList = ArrayList<Fruit>()
override fun onCreate(savedInstanceState: Bundle?) {
......
val layoutManager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
recyclerView.layoutManager = layoutManager
val adapter = FruitAdapter(fruitList)
recyclerView.adapter = adapter
}
......
private fun getRandomLengthString(str: String): String {
val n = (1..20).random()
val builder = StringBuilder()
repeat(n) {
builder.append(str)
}
return builder.toString()
}
}
GridLayoutManager 很简单修改如下
val layoutManager = GridLayoutManager(this, 3)
recyclerView.layoutManager = layoutManager
点击事件
class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHoler>() {
......
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHoler {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_fruit,parent,false)
val viewHoler = ViewHoler(view)
viewHoler.itemView.setOnClickListener {
val position = viewHoler.adapterPosition
val fruit = fruitList[position]
Toast.makeText(parent.context,fruit.name,Toast.LENGTH_SHORT).show()
}
return viewHoler
}
......
}
编写一个聊天界面
页面布局 activity_main
<?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"
android:background="#d8e0e8"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="send" />
</LinearLayout>
</LinearLayout>
左边消息布局 msg_left_item
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/leftMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"/>
</FrameLayout>
右边布局 msg_right_item
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/rightMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"/>
</FrameLayout>
创建一个消息实体类
class Msg(val content:String,val type:Int) {
companion object{
const val TYPE_RECEIVED = 0
const val TYPE_SENT = 1
}
}
创建 MsgAdapter
class MsgAdapter(val msgList: List<Msg>):RecyclerView.Adapter<RecyclerView.ViewHolder> (){
inner class LeftViewHolder(view:View):RecyclerView.ViewHolder(view){
val leftMsg:TextView = view.findViewById(R.id.leftMsg)
}
inner class RightViewHolder(view:View):RecyclerView.ViewHolder(view){
val rightMsg:TextView = view.findViewById(R.id.rightMsg)
}
override fun getItemViewType(position: Int): Int {
return msgList[position].type
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
if (viewType == Msg.TYPE_RECEIVED){
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_left_item,parent,false)
LeftViewHolder(view)
}else{
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_right_item,parent,false)
RightViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val msg = msgList[position]
when(holder){
is LeftViewHolder -> holder.leftMsg.text = msg.content
is RightViewHolder -> holder.rightMsg.text = msg.content
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int = msgList.size
}
MainActivity
class MainActivity : AppCompatActivity(),View.OnClickListener {
private val msgList = ArrayList<Msg>()
private var adapter: MsgAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initMsg()
adapter = MsgAdapter(msgList)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
button.setOnClickListener(this)
}
private fun initMsg(){
msgList.add(Msg("Hello guys",Msg.TYPE_RECEIVED))
msgList.add(Msg("Hello,who's that",Msg.TYPE_SENT))
msgList.add(Msg("This is Tom,Nice talking to you",Msg.TYPE_RECEIVED))
}
override fun onClick(v: View?) {
when(v){
button -> {
val content = editText.text.toString()
if(content.isNotEmpty()){
msgList.add(Msg(content,Msg.TYPE_SENT))
adapter?.notifyItemInserted(msgList.size-1)
recyclerView.scrollToPosition(msgList.size-1)
editText.setText("")
}
}
}
}
}
延迟初始化和密封类 中对代码进行了部分优化