前言:
很久之前,写了一篇关于ListView点击置顶操作的小笔记,后面一直由于自己目前在做测试相关的工作,也没有太多的时间来写RecyclerView点击置顶操作的笔记,特意抽空复习了一下,以此勉励自己,不能学了就忘,如有错误的地方,还请指正,谢谢
recyclerView是比ListView功能更强大的一种布局,也更能随自己的心意来更改显示的样式,如ListView,GridView,瀑布流模型,多类型布局等,这也是比较常用的一些布局,废话不多说,开始看代码:
主活动
package com.example.a05_recyclerviewtestdemo
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.example.a05_recyclerviewtestdemo.adapter.GridViewAdapter
import com.example.a05_recyclerviewtestdemo.adapter.RecyclerViewAdapter
import com.example.a05_recyclerviewtestdemo.adapter.StaggerViewAdapter
import com.example.a05_recyclerviewtestdemo.base.BaseAdapter
import com.example.a05_recyclerviewtestdemo.bean.Fruit
import com.example.a05_recyclerviewtestdemo.utils.FruitData
import java.util.*
import javax.security.auth.callback.Callback
import javax.security.auth.callback.CallbackHandler
import kotlin.collections.ArrayList
class MainActivity : AppCompatActivity() {
companion object{
private const val TAG = "MainActivity"
private lateinit var recyclerView:RecyclerView;
private lateinit var fruits:ArrayList<Fruit>;
private lateinit var adapter: BaseAdapter;
@SuppressLint("StaticFieldLeak")
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
private const val PULL_TO_FRESH = 1 //下拉刷新
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initData()
showList(isVertical = true, isReverse = false)
//监听刷新状态
swipeRefreshListener()
//添加分割线
recyclerView.addItemDecoration(DividerItemDecoration(this))
}
@SuppressLint("ResourceAsColor")
private fun swipeRefreshListener() {
swipeRefreshLayout.setOnRefreshListener {
handler.sendEmptyMessageDelayed(PULL_TO_FRESH, 3000)
}
swipeRefreshLayout.setColorSchemeColors(R.color.purple_500, R.color.purple_200, R.color.purple_700)
}
//模拟网络请求,子线程不能操作主线程,所以使用Handler来绘制UI
private val handler:Handler = @SuppressLint("HandlerLeak")
object : Handler(){
@SuppressLint("NotifyDataSetChanged")
override fun handleMessage(msg: Message) {
Log.i(TAG, "handleMessage: ")
when(msg.what){
PULL_TO_FRESH -> {
if (fruits.size > 0){
fruits.removeAt(0) //删除第一条
adapter.notifyDataSetChanged()
swipeRefreshLayout.isRefreshing = false //false:刷新完成,true:刷新完成
}
}
}
}
}
//初始化数据
private fun initData() {
Log.i(TAG, "initData: ")
recyclerView = findViewById(R.id.recyclerView)
swipeRefreshLayout = findViewById(R.id.swipRefreshLayout)
fruits = ArrayList()
FruitData.map.entries.forEach {
val fruit = Fruit()
fruit.name = it.key
fruit.img = it.value
fruits.add(fruit)
}
Log.i(TAG, "initData: fruits:$fruits")
}
/**
* 加载菜单
* @param menu Menu
* @return Boolean
*/
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return super.onCreateOptionsMenu(menu)
}
//菜单选择项
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
//listView
R.id.list_view_vertical -> showList(isVertical = true, isReverse = false)
R.id.list_view_vertical_reverse -> showList(isVertical = true, isReverse = true)
R.id.list_view_horizontal -> showList(false, isReverse = false)
R.id.list_view_horizontal_reverse -> showList(false, isReverse = true)
//GridView
R.id.grid_view_vertical -> showGrid(isVertical = true, isReverse = false)
R.id.grid_view_vertical_reverse -> showGrid(isVertical = true, isReverse = true)
R.id.grid_view_horizontal -> showGrid(false, isReverse = false)
R.id.grid_view_horizontal_reverse -> showGrid(false, isReverse = true)
//StaggerView
R.id.stagger_view_vertical -> showStagger(isVertical = true, isReverse = false)
R.id.stagger_view_vertical_reverse -> showStagger(isVertical = true, isReverse = true)
R.id.stagger_view_horizontal -> showStagger(false, isReverse = false)
R.id.stagger_view_horizontal_reverse -> showStagger(false, isReverse = true)
//moretype
R.id.moretype -> showMoreType()
}
return super.onOptionsItemSelected(item)
}
private fun showMoreType() {
//跳转到另外一个Activity中显示
val intent = Intent(this,MoreTypeActivity::class.java)
startActivity(intent)
}
private fun showList(isVertical:Boolean, isReverse:Boolean) {
//是否是垂直布局
val orientation = if(isVertical) RecyclerView.VERTICAL else RecyclerView.HORIZONTAL
//设置布局管理器
val linearLayoutManager = LinearLayoutManager(this)
linearLayoutManager.orientation = orientation
linearLayoutManager.reverseLayout = isReverse
recyclerView.layoutManager = linearLayoutManager
//获取adapter
adapter = RecyclerViewAdapter(fruits)
recyclerView.adapter = adapter
setItemClick()
}
private fun setItemClick() {
adapter.setRecyclerViewItemClick(object : BaseAdapter.RecyclerViewItemClickListener{
override fun onItemClick(realPosition: Int) {
Log.i(TAG, "onItemClick: position:${realPosition + 1}")
updateLists(realPosition)
}
})
}
//简单的置顶操作,使点击的Item与ReclerView列表的第0个元素交换位置
@SuppressLint("NotifyDataSetChanged")
private fun updateLists(realPosition: Int) {
Collections.swap(fruits, realPosition, 0)
adapter.notifyDataSetChanged()
}
private fun showStagger(isVertical: Boolean, isReverse: Boolean) {
//是否是出垂直布局
val orientation = if (isVertical) StaggeredGridLayoutManager.VERTICAL else StaggeredGridLayoutManager.HORIZONTAL
val staggeredGridLayoutManager = StaggeredGridLayoutManager(3,orientation)
//是否反转
staggeredGridLayoutManager.reverseLayout = isReverse
//设置布局管理器
recyclerView.layoutManager = staggeredGridLayoutManager
//适配器
adapter = StaggerViewAdapter(fruits)
recyclerView.adapter = adapter
setItemClick()
}
@SuppressLint("WrongConstant")
private fun showGrid(isVertical: Boolean, isReverse: Boolean) {
//是否是垂直布局
val orientation = if (isVertical) GridLayoutManager.VERTICAL else GridLayoutManager.HORIZONTAL
val gridLayoutManager = GridLayoutManager(this, 2)
gridLayoutManager.reverseLayout = isReverse
gridLayoutManager.orientation = orientation
//设置布局管理器
recyclerView.layoutManager = gridLayoutManager
//适配器
adapter = GridViewAdapter(fruits)
recyclerView.adapter = adapter
setItemClick()
}
}
然后就是分别对应于ListView,GridView,瀑布流模型的代码了,这里由于有大量重复的代码,所以一抽取了一个Base类作为基类,使得代码更加简洁:
package com.example.a05_recyclerview.base
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.a05_recyclerview.R
import com.example.a05_recyclerview.bean.Fruit
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/13 上午10:12
* @version 1.0
*/
abstract class BaseAdapter(var datas: ArrayList<Fruit>) :
RecyclerView.Adapter<BaseAdapter.MyViewHolder>() {
private var mOnItemClickListener: OnItemClickListener ?= null
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textView:TextView ?= null
var imageView:ImageView ?= null
init {
textView = itemView.findViewById(R.id.title)
imageView = itemView.findViewById(R.id.icon)
}
fun setData(fruit: Fruit) {
textView?.text = fruit.fruitName
imageView?.setImageResource(fruit.fruitImg)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView:View = getSubView(parent, viewType)
return MyViewHolder(itemView)
}
abstract fun getSubView(parent: ViewGroup, viewType: Int): View
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//获取位置信息
holder.setData(datas[position])
holder.itemView.setOnClickListener {
mOnItemClickListener?.OnItemClick(position)
}
}
override fun getItemCount(): Int {
return datas.size
}
fun setOnItemClickListener(listener:OnItemClickListener) {
//设置监听,其实就是要设置一个回调的接口
this.mOnItemClickListener = listener
}
/**
* 编写回调的步骤
* 1。创建接口
* 2. 定义接口内部的方法
* 3. 外部设置接口(其实就是接口方法外部的实现)
* 4. 接口方法的调用
*/
interface OnItemClickListener{
fun OnItemClick(position: Int)
}
companion object {
private const val TAG = "BaseAdapter"
}
}
然后各个适配器就分别继承自这个Base类就好了
ListViewAdapter:
package com.example.a05_recyclerview.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.a05_recyclerview.R
import com.example.a05_recyclerview.base.BaseAdapter
import com.example.a05_recyclerview.bean.Fruit
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/9 上午10:39
* @version 1.0
*/
class RecyclerViewAdapter(datas: ArrayList<Fruit>) : BaseAdapter(datas) {
@SuppressLint("InflateParams")
override fun getSubView(parent: ViewGroup, viewType: Int): View {
return LayoutInflater.from(parent.context).inflate(R.layout.recycler_view_item, null)
}
}
GridViewAdapter:
package com.example.a05_recyclerview.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.a05_recyclerview.R
import com.example.a05_recyclerview.base.BaseAdapter
import com.example.a05_recyclerview.bean.Fruit
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/12 下午9:41
* @version 1.0
*/
class GridViewAdapter(datas: ArrayList<Fruit>) : BaseAdapter(datas) {
@SuppressLint("InflateParams")
override fun getSubView(parent: ViewGroup, viewType: Int): View {
return LayoutInflater.from(parent.context).inflate(R.layout.grid_view_item, null)
}
}
瀑布流模型:StaggerViewAdapter:
package com.example.a05_recyclerview.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.a05_recyclerview.R
import com.example.a05_recyclerview.bean.Fruit
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/12 下午11:01
* @version 1.0
*/
class StaggerViewAdapter(datas: ArrayList<Fruit>) :
com.example.a05_recyclerview.base.BaseAdapter(datas) {
@SuppressLint("InflateParams")
override fun getSubView(parent: ViewGroup, viewType: Int): View {
return LayoutInflater.from(parent.context).inflate(R.layout.stagger_view_item,null)
}
}
多样式布局的化,设计到多种类型,所以这里选择从MainActivity跳转到另外的Activity进行显示,所以这里就有Activity之间的跳转的相关知识点
activity1:onCreate -> onStart -> onResume -> onPause
activity2: onCreate -> onStart -> onResume -> activity1 onStop
看MoreTypeActivity:
package com.example.a05_recyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.a05_recyclerview.adapter.MoreTypeAdapter
import com.example.a05_recyclerview.bean.MoreType
import com.example.a05_recyclerview.utils.FruitData
import java.util.*
import kotlin.collections.ArrayList
class MoreTypeActivity : AppCompatActivity() {
private var datas:ArrayList<MoreType> ?= null
private var recyclerView:RecyclerView ?= null
private var adapter:MoreTypeAdapter ?= null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_more_view)
initData()
showList()
recyclerView?.addItemDecoration(DividerItemDecoration(this))
}
private fun showList() {
Log.i(TAG, "showList: ")
//设置布局管理器
val layoutManager = LinearLayoutManager(this)
recyclerView?.layoutManager = layoutManager
//设置适配器
adapter = datas?.let { MoreTypeAdapter(it) }
Log.i(TAG, "showList: ${datas.toString()}")
recyclerView?.adapter = this.adapter
}
private fun initData() {
Log.i(TAG, "initData: ")
recyclerView = findViewById(R.id.more_type)
val random = Random()
datas = ArrayList()
FruitData.map.entries.forEach{
val moreType = MoreType()
moreType.icon = it.key
moreType.title = it.value
moreType.type = random.nextInt(3)
Log.i(TAG, "initData: type: ${moreType.type}")
datas?.add(moreType)
}
Log.i(TAG, "initData: ${datas.toString()}")
}
companion object {
private const val TAG = "MoreTypeActivity"
}
}
显示的实体类有以下两个:
1. MainActivity中的Fruit
package com.example.a05_recyclerview.bean
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/14 下午3:53
* @version 1.0
*/
class Fruit{
internal var fruitName:String ?= null
internal var fruitImg:Int = 0
}
2. MoreTypeActivity中的MoreType
package com.example.a05_recyclerview.bean
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/15 下午2:55
* @version 1.0
*/
class MoreType {
internal var type:Int = 0
internal var icon:Int = 0
internal var title:String ?= null
override fun toString(): String {
return "MoreType(type=$type, icon=$icon, title=$title)"
}
}
以及一个图片的集合工具类
package com.example.a05_recyclerview.utils
import com.example.a05_recyclerview.R
import com.example.a05_recyclerview.bean.Fruit
/**
* @description: TODO
* @author yueqingh
* @date 2022/6/14 下午5:58
* @version 1.0
*/
class FruitData {
companion object{
val map = hashMapOf<Int,String>(
R.mipmap.pic01 to "哈密瓜",
R.mipmap.pic02 to "梨",
R.mipmap.pic03 to "榴莲",
R.mipmap.pic04 to "樱桃",
R.mipmap.pic05 to "橙子",
R.mipmap.pic06 to "火龙果",
R.mipmap.pic07 to "猕猴桃",
R.mipmap.pic08 to "芒果",
R.mipmap.pic09 to "苹果",
R.mipmap.pic10 to "荔枝",
R.mipmap.pic11 to "西瓜",
R.mipmap.pic12 to "香蕉"
)
}
}
由于暂时还没有复习到Fragment所以暂时不使用fragment来进行多类型布局的展示,仅使用activity,这有助于记住活动的生命周期,以及活动之间跳转生命周期的变化
效果视频:
不做展示,代码及全部代码,除了自定义分割线的代码未展示,其余代码亲测可用