Android 显示“加载更多”按钮“回收器”视图的末尾
我有recyler视图,每页显示列表5项。但我不想要无休止的滚动或自动加载。但我想在列表的末尾显示加载更多按钮,当用户单击“加载更多”按钮时,将加载下一个数据。我已经证明了这一点。但问题是,当加载更多时,单击按钮加载更多混乱。并将最后一项从第一页复制到第二页 这是我的循环水Android 显示“加载更多”按钮“回收器”视图的末尾,android,android-recyclerview,Android,Android Recyclerview,我有recyler视图,每页显示列表5项。但我不想要无休止的滚动或自动加载。但我想在列表的末尾显示加载更多按钮,当用户单击“加载更多”按钮时,将加载下一个数据。我已经证明了这一点。但问题是,当加载更多时,单击按钮加载更多混乱。并将最后一项从第一页复制到第二页 这是我的循环水 abstract class BaseAdapter<T, Y: BaseViewHolder>( private val isLoadMore: Boolean = false ): RecyclerV
abstract class BaseAdapter<T, Y: BaseViewHolder>(
private val isLoadMore: Boolean = false
): RecyclerView.Adapter<BaseViewHolder>() {
private var loadMoreListener = object : LoadMoreListener {
override fun onLoadMore() {
onLoad()
}
}
private val listUpdateCallback = object :ListUpdateCallback{
override fun onChanged(position: Int, count: Int, payload: Any?) {
notifyItemRangeChanged(position, count, payload)
}
override fun onInserted(position: Int, count: Int) {
notifyItemRangeInserted(position, count)
}
override fun onMoved(fromPosition: Int, toPosition: Int) {
notifyItemMoved(fromPosition, toPosition)
}
override fun onRemoved(position: Int, count: Int) {
notifyItemRangeRemoved(position, count)
}
}
private val itemDiffCallback = object : DiffUtil.ItemCallback<T>(){
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return this@BaseAdapter.areContentsTheSame(oldItem, newItem)
}
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
return this@BaseAdapter.areItemsTheSame(oldItem, newItem)
}
}
val data = AsyncListDiffer<T>(listUpdateCallback, AsyncDifferConfig.Builder<T>(itemDiffCallback).build())
protected abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean
protected abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean
open fun updateList(items: List<T>) = data.submitList(items)
open fun updateList(items: List<T>, callback: Runnable) = data.submitList(items, callback)
override fun getItemCount(): Int = if (isLoadMore && data.currentList.isNotEmpty()) {
data.currentList.size + 1
} else {
data.currentList.size
}
private fun getActual(index: Int): T? = if (isLoadMore && (index == items.size-1)) null else items[index]
fun get(index: Int): T = if (isLoadMore && index == (data.currentList.size)) {
data.currentList[index-1]
} else {
data.currentList[index]
}
val items: List<T> get() = data.currentList
open fun onLoad(){ }
@Suppress("UNCHECKED_CAST")
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
if (isLoadMore && (position == items.size)){
(holder as LoadMoreViewHolder).hideLoading()
return
}
onBindHolder(holder as Y, position)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return if (viewType == -1) {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.item_load_more_loading, parent, false)
LoadMoreViewHolder(loadMoreListener, v)
}else{
onCreateHolder(parent, viewType)
}
}
abstract fun onBindHolder(holder: Y, position: Int)
abstract fun onCreateHolder(parent: ViewGroup, viewType: Int): Y
override fun getItemViewType(position: Int): Int {
return if (isLoadMore && (position == items.size)){
-1
}else{
super.getItemViewType(position)
}
}
class LoadMoreViewHolder(
private val listener: LoadMoreListener,
view: View
): BaseViewHolder(view){
init {
itemView.i_load_more.setOnClickListener {
showLoading()
listener.onLoadMore()
}
hideLoading()
}
private fun showLoading(){
itemView.i_progress_load.visibility = View.VISIBLE
itemView.i_load_more.visibility = View.GONE
}
fun hideLoading(){
itemView.i_progress_load.visibility = View.GONE
itemView.i_load_more.visibility = View.VISIBLE
}
}
interface LoadMoreListener{
fun onLoadMore()
}
}
抽象类BaseAdapter(
private val isLoadMore:Boolean=false
):RecyclerView.Adapter(){
私有变量loadMoreListener=对象:loadMoreListener{
覆盖有趣的onLoadMore(){
onLoad()
}
}
private val listUpdateCallback=对象:listUpdateCallback{
更改后覆盖乐趣(位置:Int,计数:Int,有效负载:Any?){
NotifyItemRange已更改(位置、计数、有效负载)
}
覆盖未插入(位置:Int,计数:Int){
notifyItemRangeInserted(位置、计数)
}
移动时覆盖乐趣(fromPosition:Int,toPosition:Int){
notifyItemMoved(从位置、位置)
}
已移除覆盖(位置:Int,计数:Int){
notifyItemRangeRemoved(位置、计数)
}
}
private val itemDiffCallback=对象:DiffUtil.ItemCallback(){
覆盖内容相同(旧项:T,新项:T):布尔值{
返回this@BaseAdapter.areContentsTheSame(旧项目,新项目)
}
覆盖乐趣项相同(旧项:T,新项:T):布尔值{
返回this@BaseAdapter.areItemsTheSame(旧项目,新项目)
}
}
val data=AsyncListDifference(listUpdateCallback,AsyncDifferConfig.Builder(itemDiffCallback.build())
受保护的抽象趣味内容相同(旧项:T,新项:T):布尔值
受保护的抽象项相同(旧项:T,新项:T):布尔值
打开乐趣更新列表(项目:列表)=数据。提交列表(项目)
open fun updateList(项:列表,回调:Runnable)=data.submitList(项,回调)
重写fun getItemCount():Int=if(isLoadMore&&data.currentList.IsNoteEmpty()){
data.currentList.size+1
}否则{
data.currentList.size
}
private-fun-getActual(index:Int):T?=if(isLoadMore&&(index==items.size-1))null-else项[index]
fun get(index:Int):T=if(isLoadMore&&index==(data.currentList.size)){
data.currentList[索引-1]
}否则{
data.currentList[索引]
}
val items:List get()=data.currentList
打开fun onLoad(){}
@抑制(“未选中的_CAST”)
覆盖BindViewHolder(holder:BaseViewHolder,位置:Int){
if(isLoadMore&(position==items.size)){
(保持架作为LoadMoreViewHolder).hideLoading()
返回
}
ON活页夹(活页夹为Y,位置)
}
重写CreateViewHolder(父级:ViewGroup,viewType:Int):BaseViewHolder{
返回if(viewType==-1){
val v=LayoutInflater.from(parent.context)
.充气(R.layout.item\u load\u more\u loading,父项,错误)
LoadMoreViewHolder(loadMoreListener,v)
}否则{
onCreateHolder(父级,视图类型)
}
}
活页夹(活页夹:Y,位置:Int)
抽象元素onCreateHolder(父对象:ViewGroup,viewType:Int):Y
覆盖getItemViewType(位置:Int):Int{
返回if(isLoadMore&(position==items.size)){
-1
}否则{
super.getItemViewType(位置)
}
}
类LoadMoreViewHolder(
私有val侦听器:LoadMoreListener,
视图:视图
):BaseViewHolder(视图){
初始化{
itemView.i\u load\u more.setOnClickListener{
showLoading()
listener.onLoadMore()
}
hideLoading()
}
私人娱乐节目{
itemView.i\u progress\u load.visibility=View.VISIBLE
itemView.i\u load\u more.visibility=View.GONE
}
趣味阅读{
itemView.i\u progress\u load.visibility=View.GONE
itemView.i\u load\u more.visibility=View.VISIBLE
}
}
接口LoadMoreListener{
乐趣在线下载更多()
}
}
这是我的基本适配器的实现
class CommentAdapter(
private val listener: (item: Click)->Unit
): BaseAdapter<Comment, CommentAdapter.Holder>(true){
override fun areContentsTheSame(oldItem: Comment, newItem: Comment): Boolean {
return oldItem.id == newItem.id &&
oldItem.message == newItem.message &&
oldItem.nicknameName == newItem.nicknameName &&
oldItem.replyCount == newItem.replyCount &&
oldItem.stickerImage == newItem.stickerImage &&
oldItem.createAt == newItem.createAt
}
override fun areItemsTheSame(oldItem: Comment, newItem: Comment): Boolean {
return oldItem.id == newItem.id
}
override fun onBindHolder(holder: Holder, position: Int) {
holder.bind(get(position))
}
override fun onCreateHolder(parent: ViewGroup, viewType: Int): Holder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.item_comment, parent, false)
return Holder(listener, v)
}
override fun onLoad() {
listener(Click.OnLoadMore)
}
class Holder(
private val listener: (item: Click)->Unit,
view: View
): BaseViewHolder(view){
private var item: Comment? = null
private val sharedPreference: ISharedPreference = SharedPreference(itemView.context)
init {
itemView.setOnClickListener {
item?.let {
listener(Click.View(it))
}
}
}
fun bind(item: Comment){
this.item = item
Glide.with(itemView.context)
.load(Media.downloadProfile(item.profileName))
.into(itemView.item_comment_profile)
itemView.item_text_nickname.text = item.nicknameName
itemView.item_text_time.text = DateTime.parse(item.createAt).toString()
if (sharedPreference.loadFirebaseId() == item.id){
itemView.item_text_identity.visibility = View.VISIBLE
itemView.item_text_identity.text = StringBuilder("You")
}else{
itemView.item_text_identity.visibility = View.INVISIBLE
}
if (item.stickerImage != "" && item.message != ""){
inflateTextSticker()
}else if(item.stickerImage != "" && item.message == ""){
inflateSticker()
}else if(item.stickerImage == "" && item.message != ""){
inflateText()
}
inflateReply()
}
private fun inflateReply(){
itemView.item_stub_count.layoutResource = R.layout.view_comment_count
val view = itemView.item_stub_count.inflate()
view.item_text_reply_count.text = StringBuilder(
"-------- View ${item!!.replyCount} reply"
)
view.item_button_option.setOnClickListener {
listener(Click.Options(item!!))
}
}
private fun inflateSticker(){
itemView.item_stub_content.layoutResource = R.layout.view_comment_sticker
val view = itemView.item_stub_content.inflate()
Glide.with(itemView.context)
.load(Media.downloadSticker(item!!.stickerId, item!!.stickerImage))
.into(view.view_comment_sticker)
}
private fun inflateText(){
itemView.item_stub_content.layoutResource = R.layout.view_comment_text
val view = itemView.item_stub_content.inflate()
view.view_text_content.text = item!!.message
}
private fun inflateTextSticker(){
itemView.item_stub_content.layoutResource = R.layout.view_comment_sticker_text
val view = itemView.item_stub_content.inflate()
Glide.with(itemView.context)
.load(Media.downloadSticker(item!!.stickerId, item!!.stickerImage))
.into(view.view_comment_sticker_sticker)
view.view_comment_sticker_text_content.text = item!!.message
}
}
sealed class Click{
class Options(val item: Comment): Click()
class View(val item: Comment): Click()
object OnLoadMore: Click()
}
}
class注释适配器(
专用val侦听器:(项目:单击)->单位
):BaseAdapter(真){
覆盖内容相同(旧项:注释,新项:注释):布尔值{
返回oldItem.id==newItem.id&&
oldItem.message==newItem.message&&
oldItem.昵称名称==newItem.昵称名称&&
oldItem.replyCount==newItem.replyCount&&
oldItem.stickerImage==newItem.stickerImage&&
oldItem.createAt==newItem.createAt
}
覆盖乐趣项相同(旧项:注释,新项:注释):布尔值{
返回oldItem.id==newItem.id
}
覆盖绑定保持架(保持架:保持架,位置:Int){
固定器绑定(获取(位置))
}
重写onCreateHolder(父级:ViewGroup,viewType:Int):Holder{
val v=LayoutInflater.from(parent.context)
.充气(R.layout.item_注释,父项,假)
返回支架(侦听器,v)
}
覆盖乐趣加载(){
侦听器(单击.OnLoadMore)
}
阶级持有者(
专用val侦听器:(项目:单击)->单位,
视图:视图
):BaseViewHolder(视图){
私有变量项:注释?=null
private val sharedPreference:ISharedPreference=sharedPreference(itemView.context)
初始化{
itemView.setOnClickListener{
项目?让我们{
侦听器(单击。查看(it))
}
}
}
趣味绑定(项目:注释){
this.item=项目
Glide.with(itemView.context)
.load(媒体)下载配置文件(项目