在Android回收站视图中显示“加载更多”按钮结尾

时间:2019-10-08 09:02:23

标签: android android-recyclerview recycler-adapter

我有Recyler视图显示每页5个项目。但我不想无休止的滚动或自动加载。但是我想显示加载更多按钮列表的末尾,当用户单击该“加载更多”按钮将加载下一个数据。我已经成功表明了这一点。但是问题是当加载更多时,单击按钮加载更多的混乱。并将第一页的最后一项复制到第二页。

这是我的RecycleViewAdapter

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()
    }
}

这是我的基本适配器工具

    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()
    }
}

0 个答案:

没有答案