Android GridLayoutManager RecyclerView page load/paging load,by calculate screen position from already loaded item's position,kotlin(3)
package my.application
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
class MainActivity : AppCompatActivity() {
companion object {
val TAG = "fly"
}
val PAGE_SIZE = 50 //每一页的数据总数
var PAGE_COUNT = 0 //记录已经加载的页数
val mAdapter = MyAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.layoutManager = GridLayoutManager(this, 4).apply {
orientation = GridLayoutManager.VERTICAL
}
//假设已经知道全量数据,后续的分段是把源数据一片一片的截出来,装到新的分页数据集里面
val ITEMS = ArrayList<MyData>()
for (i in 0..1000) {
var data = MyData("$i", "@$i")
ITEMS.add(data)
}
recyclerView.adapter = mAdapter
var mIsLoading = false
var rang = IntArray(2) { 0 }
recyclerView.addOnScrollListener(object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (mIsLoading) {
Log.d(TAG, "正在加载!")
return
}
getOutRange(recyclerView, rang)
var pos = ITEMS.size - PAGE_SIZE * PAGE_COUNT
Log.d(TAG, "onScrolled ${rang[0]}->${rang[1]} $pos")
if (rang[0] - pos < PAGE_SIZE) {
mIsLoading = true
PAGE_COUNT++
Log.d(TAG, "load $PAGE_COUNT ->")
paging(ITEMS, PAGE_SIZE, PAGE_COUNT)
Log.d(TAG, "load $PAGE_COUNT <-")
mIsLoading = false
}
}
})
PAGE_COUNT = 1
paging(ITEMS, PAGE_SIZE, PAGE_COUNT)
//recyclerView启动后默认滚到最底部
recyclerView.scrollToPosition(mAdapter.getItemCount() - 1)
}
fun paging(
sourceItems: ArrayList<MyData>,
pageSize: Int,
pageCount: Int
) {
Log.d(TAG, "加载第 $pageCount 页")
//新的分页数据集
var pageItems: ArrayList<MyData>? = ArrayList()
var count = pageCount * pageSize
if (count > sourceItems.size) {
//因为分页是基于整数PAGE_SIZE分页的,很可能PAGE_SIZE * PAGE_COUNT大于实际sourceItems长度
pageItems = sourceItems.toList() as ArrayList<MyData>
} else {
var pos = sourceItems.size - pageSize * pageCount
for (i in 0 until pos) {
//上部分加入占位数据
pageItems?.add(MyData("-1", "-1"))
}
for (i in 0 until count) {
//截取真实的源数据到新的分页数据items里面
pageItems?.add(sourceItems.get(pos + i)!!)
}
}
mAdapter.onChange(pageItems!!)
}
fun getOutRange(rv: RecyclerView, outRange: IntArray) {
outRange[0] = (rv.layoutManager as GridLayoutManager?)!!.findFirstVisibleItemPosition()
outRange[1] = (rv.layoutManager as GridLayoutManager?)!!.findLastVisibleItemPosition()
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
package my.application
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class MyAdapter() : RecyclerView.Adapter<MyViewHolder>() {
var items: ArrayList<MyData>? = ArrayList()
fun onChange(items: ArrayList<MyData>) {
this.items?.clear()
this.items = items
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(android.R.layout.simple_list_item_2, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return items?.size!!
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.name.text = items?.get(position)?.name
holder.desc.text = items?.get(position)?.desc
}
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val name: TextView = itemView.findViewById(android.R.id.text1)
val desc: TextView = itemView.findViewById(android.R.id.text2)
}
data class MyData(var name: String, var desc: String)