实现上拉加载更多主要有3步
代码如下(示例):
class MyAdapter(val data : List<String>): RecyclerView.Adapter<RecyclerView.ViewHolder>(){
private val footView = 1 // 定义变量,对应不同的情况
private val normalView = 0
private val footStart = 2
private val footEnd = 3
private val footNoMore = 4
private var footState = 0
class MyVH(view: View):RecyclerView.ViewHolder(view) {
// 普通的ViewHolder
val textNormal = view.findViewById<TextView>(R.id.textView)
}
class FootVH(view: View): RecyclerView.ViewHolder(view) {
// 显示"正在加载中"界面的ViewHolder
val textFoot = view.findViewById<TextView>(R.id.tv_my_more)
val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)
}
override fun getItemViewType(position: Int): Int {
// 返回应该加载哪种类型的ViewHodler
if (position + 1 == itemCount) {
// 说明已经滑动到最底部了
return footView
} else {
return normalView
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
// 创建不同的ViewHodler,但是都是继承自RecyclerView.ViewHolder
if (viewType == normalView) {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_text, parent, false) // 正常显示内容的 view
return MyVH(view)
}else {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_more, parent, false) // footView
return FootVH(view)
}
}
override fun getItemCount(): Int {
// 返回数据个数加1,因为多一个用来显示 “正在加载中”界面的item
return data.size + 1
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is MyVH) {
holder.textNormal.text = data[position]
} else if (holder is FootVH) {
if (footState == 2) {
// 正在加载中
holder.textFoot.visibility = View.VISIBLE
holder.progressBar.visibility = View.VISIBLE
}else if (footState == 3) {
// 加载结束
holder.textFoot.visibility = View.GONE
holder.progressBar.visibility = View.GONE
}else if (footState == 4) {
// 没有更多数据可以加载了
holder.progressBar.visibility = View.GONE
holder.textFoot.text = "没有更多数据啦"
}
}
}
fun setFootState(state: Int) {
// 设置不同的 footState
footState = state
notifyDataSetChanged() // 更新 Adapter 数据
}
}
定义一个抽象类,减少Activity中对RecyclerView的监听代码
代码如下(示例):
abstract class EndRecyclerOnScrollListener: RecyclerView.OnScrollListener(){
private var flag = 0
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
val layout = recyclerView.layoutManager as LinearLayoutManager
val lastPositionCompletely = layout.findLastCompletelyVisibleItemPosition()
if (lastPositionCompletely == layout.itemCount - 1 && flag == 0) {
loadMore()
}
}
abstract fun loadMore()
fun setFlag(flag: Int) {
// 设置标记防止多次向上滑动,多次调用 loadMore()
this.flag = flag
}
}
class MainActivity : AppCompatActivity() {
private val data = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.layoutManager = LinearLayoutManager(this)
getData()
val adapter = MyAdapter(data)
recyclerView.adapter = adapter
recyclerView.addOnScrollListener(object : EndRecyclerOnScrollListener() {
// 匿名内部类实现接口
override fun loadMore() {
// 具体获取数据的逻辑
setFlag(1) // 设置flag = 1,向上滑动,监听事件会继续触发,但是不会继续加载数据
adapter.setFootState(2) // 设置 FootView 的初始状态
Timer().schedule(object : TimerTask() {
// 延时执行
override fun run() {
if (adapter.itemCount < 52) {
runOnUiThread{
getData()
adapter.setFootState(3) // 加载完成
setFlag(0) // 此次数据加载完毕,设置flag = 0,以便下次数据可以加载
}
}else {
runOnUiThread {
adapter.setFootState(4) // 没有更多数据加载了
}
}
}
}, 1000)
}
})
}
fun getData() {
var s = 'A'
for (i in 0..25) {
data.add(s.toString())
s++
}
}
}
至此已经实现了上拉加载更多的功能,不过此时如果其他 RecyclerView 也要实现上拉加载更多,就要写许多重复代码在 Adapter 中,为了减少重复代码,下面对 Adapter 进行封装。
class LoadMoreWrapper(private val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// 因为不同Adapter的ViewHolder类型是不同的,但是都是继承自RecyclerView.ViewHolder,所以泛型指定为RecyclerView.ViewHolder
private val footView = 1
private val normalView = 0
private val footStart = 2
private val footEnd = 3
private val footNoMore = 4
private var footState = 0
class FootVH(view: View) : RecyclerView.ViewHolder(view) {
val textFoot = view.findViewById<TextView>(R.id.tv_my_more)
val progressBar = view.findViewById<ProgressBar>(R.id.progressBar)
}
override fun getItemViewType(position: Int): Int {
if (position + 1 == itemCount) {
return footView
} else {
return normalView
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder{
if (viewType == normalView) {
return adapter.onCreateViewHolder(parent, viewType) // 调用adapter的onCreateViewHolder返会正常布局
} else {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_more, parent, false)
return FootVH(view)
}
}
override fun getItemCount(): Int {
return adapter.itemCount + 1
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is FootVH) {
if (footState == 2) {
holder.textFoot.visibility = View.VISIBLE
holder.progressBar.visibility = View.VISIBLE
} else if (footState == 3) {
holder.textFoot.visibility = View.GONE
holder.progressBar.visibility = View.GONE
} else if (footState == 4) {
holder.progressBar.visibility = View.GONE
holder.textFoot.text = "没有更多数据啦"
}
} else {
adapter.onBindViewHolder(holder, position)
}
}
fun setFootState(state: Int) {
footState = state
notifyDataSetChanged()
}
}
然后Adapter中的写法就是一般的写法了
class MyAdapter(val data : List): RecyclerView.Adapter
class MyVH(view: View):RecyclerView.ViewHolder(view) {
val textNormal = view.findViewById(R.id.textView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_text, parent, false)
return MyVH(view)
}
override fun getItemCount(): Int {
return data.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder as MyVH
holder.textNormal.text = data[position]
}
}
class MainActivity : AppCompatActivity() {
private val data = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.layoutManager = LinearLayoutManager(this)
getData()
val adapter = MyAdapter(data)
val loadMoreWrapper = LoadMoreWrapper(adapter) // 封装后的Adapter
recyclerView.adapter = loadMoreWrapper
recyclerView.addOnScrollListener(object : EndRecyclerOnScrollListener() {
// 添加监听事件
override fun loadMore() {
// 加载逻辑
setFlag(1) // 设置flag = 1,向上滑动,监听事件会继续触发,但是不会继续加载数据
loadMoreWrapper.setFootState(2)
Timer().schedule(object : TimerTask() {
override fun run() {
if (adapter.itemCount < 100) {
runOnUiThread{
getData()
loadMoreWrapper.setFootState(3)
setFlag(0) // 此次数据加载完毕,设置flag = 0,以便下次数据可以加载
}
}else {
runOnUiThread{
loadMoreWrapper.setFootState(4)
}
}
}
}, 1000)
}
})
}
fun getData() {
var s = 'A'
for (i in 0..25) {
data.add(s.toString())
s++
}
}
}
参考文章 https://www.jianshu.com/p/b502c5b59998