Search code examples
androidkotlinandroid-recyclerviewnestedrecyclerview

Nested recycler view's unable to show two independent lists


I have a vertical chat recycler-view i am trying to show multiple horizontal recycler-view's in which contain a "carousel" of card views. I am able to inflate the horizontal views but when i try to add two of the same kind of horizontal view as independent items in the parent view i either get the new data added to the original and then displayed twice or if i clear the old array the new data replaces the old data in the recycler-view and a second one is not added.

I am unsure if this is due to me not generating individual adapters per horizontal view or some array issue.

My adapter generation, called in the onBindViewHolder of the parent recycler-view:

fun generateAdapter(holder: ViewHolder): CarouselAdapter{
        val layoutManager = LinearLayoutManager(appContext, LinearLayoutManager.HORIZONTAL, false )

        holder.carouselView.layoutManager = layoutManager
        val adapterCarousel = CarouselAdapter()
        holder.carouselView.adapter = adapterCarousel

        snapHelper.attachToRecyclerView(holder.carouselView)
        holder.carouselView.addItemDecoration(ItemOffsetDecoration(12))


        holder.carouselView.isNestedScrollingEnabled = false
        layoutManager.isSmoothScrollbarEnabled = true
        layoutManager.stackFromEnd = true

        return adapterCarousel
    }

Calling of data onto child recycler-view:

"rates" -> {
                if (items[i].ratesData != null) {
                    val adapter = generateAdapter(holder)
                    for (j in 0 until (items[i].ratesData!!.size)) {
                        adapter.addCarousel(ChatNew(items[i].msgTime, null, null, null, items[i].ratesData!![j], null, null, null, null))
                    }
                }
                //ParseHelper.clearArrays()

            }

Child adapter:

class CarouselAdapter : RecyclerView.Adapter<ViewHolderCarousel>() {

    private val RATES = 1
    private val IMG_BUTTON = 2
    private val IMG_NO_BUTTON = 3
    private val BLUE = 4
    private val NO_IMG_BUTTON = 5
    private val ERROR = 0

    lateinit var type : String

    var items: ArrayList<ChatNew> = ArrayList()



    fun addCarousel(carousel: ChatNew){
        items.add(carousel)

        notifyItemInserted(itemCount)

    }


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderCarousel {
        return when(viewType) {
            RATES -> RatesViewHolderNew(LayoutInflater.from(appContext).inflate(R.layout.carousel_rate, parent, false))
            IMG_BUTTON -> ImgButtonViewHolder(LayoutInflater.from(appContext).inflate(R.layout.carousel_img_btn, parent, false))
            IMG_NO_BUTTON -> ImgNoButtonViewHolder(LayoutInflater.from(appContext).inflate(R.layout.carousel_img_no_btn, parent, false))
            NO_IMG_BUTTON-> NoImgButtonViewHolder(LayoutInflater.from(appContext).inflate(R.layout.carousel_no_img_btn, parent, false))
            else -> BlueViewHolder(LayoutInflater.from(appContext).inflate(R.layout.carousel_noimg_nobtn, parent, false))
        }
    }

    override fun getItemCount(): Int {
        return items.size

    }

    override fun onBindViewHolder(holder: ViewHolderCarousel, i: Int) {
        type = findType(holder)

        when (type){
            "rates" -> {
                val ri = items[i]
                //for (i in 0 until (ri.ratesData!!.size)){
                    holder.pnView.text = ri.ratesData?.pn
                    holder.mpView.text =ri.ratesData?.mp
                    holder.itView.text = ri.ratesData?.it
                    holder.brView.text = ri.ratesData?.br
                    holder.pfView.text = ri.ratesData?.pf
                    holder.aprcView.text = ri.ratesData?.aprc
                    holder.tpView.text = ri.ratesData?.tp
                    holder.headDivider!!.setBackgroundColor(ContextCompat.getColor(appContext!!, R.color.NWBlue))
               // }

            }
            "carousel button" -> {
                val ci = items[i]
                holder.imgView.setImageResource(ci.carouselData?.img!!)
                holder.number.text = ci.carouselData?.number
                holder.title.text = ci.carouselData?.title
                holder.content.text = ci.carouselData?.content
                holder.magicString.text = ci.carouselData?.magicString

            }
            "img no button" -> {
                val ci = items[i]
                holder.imgViewNoBtn.setImageResource(ci.carouselData?.img!!)
                holder.numberNoBtn.text = ci.carouselData?.number
                holder.titleNoBtn.text = ci.carouselData?.title
                holder.contentNoBtn.text = ci.carouselData?.content
                holder.noButtonString.text = ci.carouselData?.noButtonString
            }
            "no img no button" -> {
                val ci = items[i]
                holder.imgViewNoImgNoBtn.setBackgroundColor(ContextCompat.getColor(appContext!!,R.color.NWBlue))
                holder.numberNoImgNoBtn.text = ci.carouselData?.number
                holder.titleNoImgNoBtn.text = ci.carouselData?.title
                holder.contentNoImgNoBtn.text = ci.carouselData?.content
            }
            "no img button" -> {
                val ci = items[i]
                holder.imgViewNoImg.setBackgroundColor(ContextCompat.getColor(appContext!!,R.color.NWBlue))
                holder.numberNoImg.text = ci.carouselData?.number
                holder.titleNoImg.text = ci.carouselData?.title
                holder.contentNoImg.text = ci.carouselData?.content
                holder.magicStringNoImg.text = ci.carouselData?.magicString

            }
        }
    }

    override fun getItemViewType(i: Int): Int {

        return when (items.isNotEmpty()) {
            true -> {
                when {
                    items[i].ratesData != null -> RATES
                    items[i].carouselData != null -> {
                        when (items[i].carouselData?.img != null) {
                            true -> {
                                return if (items[i].carouselData?.magicString != null) {
                                    //has image and button
                                    IMG_BUTTON
                                } else {
                                    //has image but no button
                                    IMG_NO_BUTTON
                                }
                            }
                            false -> {
                                return if (items[i].carouselData?.magicString != null) {
                                    //has no image but button
                                    NO_IMG_BUTTON
                                } else {
                                    //has no image and no button
                                    BLUE
                                }
                            }
                        }

                    }
                    else -> ERROR
                }

            }
            false -> ERROR
        }
    }



    fun findType(holder: ViewHolderCarousel): String {
        return when (holder) {
            is RatesViewHolderNew -> "rates"
            is ImgButtonViewHolder -> "carousel button"
            is ImgNoButtonViewHolder -> "img no button"
            is NoImgButtonViewHolder -> "no img button"
            is BlueViewHolder -> "no img no button"
            else -> "error"
        }
    }

}
open class ViewHolderCarousel(view: View) : RecyclerView.ViewHolder(view) {

        // looks at the view and finds components on that view
        // carousel for rates
        val headDivider: LinearLayout? = view.head_divider
        val pnView = view.pn_view
        val mpView = view.mp_view
        val itView = view.it_view
        val brView = view.br_view
        val pfView = view.pf_view
        val aprcView = view.aprc_view
        val tpView = view.tp_view

        //TODO: set up links for "r" sections

        //carousel with img and button
        val imgView = view.imageView_btn
        val number = view.number_btn
        val title = view.title_btn
        val content = view.content_btn
        val magicString = view.carousel_button_btn

        //carousel with img but no button
        val imgViewNoBtn = view.imageView_no_btn
        val numberNoBtn = view.number_no_btn
        val titleNoBtn = view.title_no_btn
        val contentNoBtn = view.content_no_btn
        val noButtonString = view.magic_string_no_btn

        //carousel with no img or button
        val imgViewNoImgNoBtn = view.imageView_no_img_no_btn
        val numberNoImgNoBtn = view.number_no_img_no_btn
        val titleNoImgNoBtn = view.title_no_img_no_btn
        val contentNoImgNoBtn = view.content_no_img_no_btn

        val imgViewNoImg = view.imageView_no_img
        val numberNoImg = view.number_no_img
        val titleNoImg = view.title_no_img
        val contentNoImg = view.content_no_img
        val magicStringNoImg = view.carousel_button_no_img

    }

class RatesViewHolderNew(itemView: View) : ViewHolderCarousel(itemView)

class ImgButtonViewHolder(itemView: View) : ViewHolderCarousel(itemView)

class ImgNoButtonViewHolder(itemView: View) : ViewHolderCarousel(itemView)

class NoImgButtonViewHolder(itemView: View) : ViewHolderCarousel(itemView)

class BlueViewHolder(itemView: View) : ViewHolderCarousel(itemView)

Any ideas on how i could ensure that each time i add a new set of carousel data it gets added as an independent item in the parent view would be appreciated.


Solution

  • It turns out that you can fix this by having each addition to the parent adapter/view as an async task. Am unsure why this works but am not complaining.

    doAsync {
     adapter.addChatMessage(Chat(time, null, null, null, contentRates, null, null, null, null))
    }