Kotlin RecyclerView 添加加载页脚

3
我已经按照这个视频实现了RecyclerView的标题:https://www.youtube.com/watch?v=ksIpDnLiCMs但是我不知道如何集成带有ProgressBar的加载底部,我尝试自己实现它,但它没有起作用,它应该在我向下滚动时加载更多,但无论我滚动到哪里都在不停地加载,并且ProgressBar不会出现。以下是我的代码:

MainActivity.kt:

class MainActivity : AppCompatActivity() {

    val numberList: MutableList<String> = ArrayList()

    var page = 1
    var isLoading = false
    var limit = 10

    lateinit var adapter: RV_Adapter
    lateinit var layoutManager: LinearLayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager

        getPage()

        recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {

                val visibleItemCount = layoutManager.childCount
                val pastVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition()
                val total = adapter.itemCount

                if(!isLoading) {
                    if((visibleItemCount + pastVisibleItem) >= total) {
                        page++
                        getPage()
                    }
                }

                super.onScrolled(recyclerView, dx, dy)
            }
        })
    }

    fun getPage() {
        isLoading = true
        //progressBar.visibility = View.VISIBLE
        val start : Int = (page-1)*limit
        val end : Int = page * limit

        for(i in start..end){
            numberList.add("PodView " + i.toString())
        }
        Handler().postDelayed({
            if(::adapter.isInitialized) {
                adapter.notifyDataSetChanged()
            } else {
                adapter = RV_Adapter(this, numberList)
                recyclerView.adapter = adapter
            }
            isLoading = false
            //progressBar.visibility = View.GONE
        }, 0)

    }
}

RV_Adapter.kt

class RV_Adapter(private val context: Context, private val numberList: MutableList<String>) : RecyclerView.Adapter<BaseViewHolder<*>>() {

    companion object {
        private const val TYPE_HEADER = 0
        private const val TYPE_ITEMS = 1
        private const val TYPE_FOOTER = 2
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> {

        return when(viewType) {
            TYPE_HEADER -> {
                val view = LayoutInflater.from(context).inflate(R.layout.rv_header, parent, false)
                HeaderViewHolder(view)
            }

            TYPE_ITEMS -> {
                val view = LayoutInflater.from(context).inflate(R.layout.listview_item, parent, false)
                ItemViewHolder(view)
            }

            TYPE_FOOTER -> {
                val view = LayoutInflater.from(context).inflate(R.layout.rv_footer, parent, false)
                FooterViewHolder(view)
            }

            else -> throw IllegalArgumentException("Invalid View Type")
        }

    }

    override fun getItemCount(): Int {
        return numberList.size + 1
    }

    override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
        if(holder is ItemViewHolder){
            holder.numberBarText.text = numberList[position]
        }
        if(holder is HeaderViewHolder){
            holder.cardView.radius = 50f
        }


    }

    override fun getItemViewType(position: Int): Int {
        if(position == 0) {
            return TYPE_HEADER
        }

        return TYPE_ITEMS
    }

    inner class HeaderViewHolder(itemView: View): BaseViewHolder<View>(itemView) {
        val cardView : CardView = itemView.findViewById(R.id.profileImageCardView)

        override fun bind(item: View) {}

    }

    inner class ItemViewHolder(itemView: View): BaseViewHolder<View>(itemView) {
        val numberBarText = itemView.findViewById<TextView>(R.id.numberBarText)

        override fun bind(item: View) {}

    }
    inner class FooterViewHolder(itemView: View): BaseViewHolder<View>(itemView) {

        override fun bind(item: View) {}

    }
}

更新:

在将我的RecyclerView与BottomNavigationView结合后,页脚和页眉出现了故障。需要更加稳固的解决方案,而不仅仅是像这样向arraylist添加字符串:numberList.add("VIEW_TYPE_FOOTER")

2个回答

1
考虑在适配器中也维护 isLoading 变量,并通过在 MainActivity 中添加以下方法来设置和取消设置它:
var isLoading:Boolean
fun setIsLoading(value:Boolean) {
    isLoading = value
}

然后你可以像这样更改方法:
override fun getItemCount(): Int {
    return numberList.size + 1
}

TO

override fun getItemCount(): Int {
    return if(!isLoading) isnumberList.size + 1 else isnumberList.size + 2 
}

并且

override fun getItemViewType(position: Int): Int {
    if(position == 0) {
        return TYPE_HEADER
    }

    return TYPE_ITEMS
}

TO

override fun getItemViewType(position: Int): Int {
    if(position == 0) {
        return TYPE_HEADER
    } else if(position == isnumberList.size + 2) {
        return TYPE_FOOTER
    }

    return TYPE_ITEMS
}

不错。现在当我滑到底部时,我的列表正在加载,但页脚进度条没有显示。 - Rondev
尝试在getPage()方法内从MainActivity加载时,在适配器上调用notifyDatasetChanged()。 - Akshay Choudhry
我已经在getPage()函数中调用了notifyDatasetChanged(),你可以在我的代码中看到。 - Rondev
如果你分享你的代码库,我可以尝试进一步帮助。 - Akshay Choudhry
经过一些尝试和错误,我可以在滚动到底部时看到页脚。但我不完全明白它是如何工作的。 我将在问题中发布更新后的函数。 - Rondev

1
为了在您的适配器中创建页脚项,您应该在代码中实现几个内容。
第一件事是,您应该为您的页脚创建一个新的itemViewType
第二件事是,您需要创建一种方法来告诉您的Adapter这个视图实际上是一个页脚。由于您正在使用ListString,因此您应该在List末尾添加类似于以下内容的东西:
numberList.add("VIEW_TYPE_FOOTER")

然后是这样的:

(保留HTML)
override fun getItemViewType(position: Int): Int {
      val item = numberList[position]
      if(position == 0) {
          return TYPE_HEADER
      } else if(item == "VIEW_TYPE_FOOTER") {
          return TYPE_FOOTER
      }
      return TYPE_ITEMS
}

你应该检查 lastVisibleItem,而不是 firstVisibleItem,并在此之后获取 nextPage。 请记住,在获取下一页后,您需要从 List 中删除最新的项,即页脚视图,将下一页添加到 List 中,然后决定是否需要添加新的页脚。 希望这可以帮助您了解如何在您的情况下使其工作。

这个技巧对我起了作用,但是当我将我的RecyclerView与底部导航栏结合使用时,一切都变得非常糟糕。所以不幸的是,这种技术对我来说并不有效。 - Rondev
你应该添加更多细节,说明问题和你正在做什么,这样我们才能提供帮助。我的回答只是一个基本想法,而不是真正的实现。 - hardartcore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接