0

here I want to put ads in recyclerview item at position 5 using banner_ads layout like this everything works fine but the Proble is, banner_ads layout replace the original item of the 5th position. means 5th item is Invisible.

What i want

banner_ads layout should be inserted at 5th postition and 5th item should be skipped at 6th position

this is banner_ads layout

 <?xml version="1.0" encoding="utf-8"?>
    <com.google.android.gms.ads.AdView
    android:visibility="visible"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    android:id="@+id/publisherAdView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    ads:adSize="SMART_BANNER"
    ads:adUnitId="ca-app-pub-3940256099942544/6300978111"
    xmlns:android="http://schemas.android.com/apk/res/android" />

Here's the whole adapter class

class Adapter(private val m: Music): RecyclerView.Adapter<MyViewHolder>(){
     private val defaulViewType = 0
     private val bannerAdsType = 1


        override fun getItemViewType(position: Int): Int {
        return if (position == 5) {
            bannerAdsType
        } else  defaulViewType
    }




    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) : MyViewHolder {

        var row : View? = null

        return when(viewType) {

            defaulViewType -> {

                val layoutInflater = LayoutInflater.from(parent.context)
                row = layoutInflater.inflate(R.layout.item, parent, false)
                MyViewHolder(row)

            }
            else -> {

                val layoutInflater = LayoutInflater.from(parent.context)
                 row = layoutInflater.inflate(R.layout.banner_ads, parent, false)
                NativeContentAdViewHolder(row)

            }
        }

    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {


        val data = m.music[position]

        if (holder.itemViewType == defaulViewType) {

            holder.itemView.findViewById<TextView>(R.id.title_song).text = data.song
            holder.itemView.findViewById<TextView>(R.id.artist).text = data.artists
            val img = holder.itemView.findViewById<ImageView>(R.id.thumbnail)
            Picasso.get().load(data.cover_image).resize(300, 250).into(img)
        }


        holder.dataList= data

    }


    override fun getItemCount(): Int {

        return m.music.count()

    }

}

here i make two ViewHolder Class one for Original Content and second is for banner_ads layout

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
open class MyViewHolder(
        view: View, var dataList: Mlist? = null,

        ): RecyclerView.ViewHolder(view){

    init {

        view.setOnClickListener{...........}
      
       }


   

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class NativeContentAdViewHolder internal constructor(view: View):MyViewHolder(view) {


    init {


        val adViewss = itemView.findViewById<AdView>(R.id.publisherAdView)
        val adRequests = AdRequest.Builder().build()
        adViewss.loadAd(adRequests)
        adViewss.adListener = object : AdListener() {

            override fun onAdLoaded() {
                // Code to be executed when an ad finishes loading.
            adViewss.visibility = View.VISIBLE
                Toast.makeText(view.context, " ad Loaded", Toast.LENGTH_SHORT).show()
            }

            override fun onAdFailedToLoad(adError: LoadAdError) {
               adViewss.visibility = View.GONE
                Toast.makeText(view.context, " ad is not Loaded", Toast.LENGTH_SHORT).show()
            }
        }
    }
 }

I have also tried to load ads from onBindViewHolder() class but I have to face same problem here's the Model Class

class Music (val music: List<MusicList> )
 class MusicList (
    val cover_image:String,
    val song : String,
    val url : String,
    val artists : String
        )
Synonian_raj
  • 154
  • 1
  • 13

1 Answers1

0

There might be different possible ways to solve this issue but none I can think of doesn't involve you mutating the adapter dataset.

You could create a special Music object and add it to dataset at the particular position you want before passing it to the recyclerView.

Let's assume m.music is a list of MusicItem:

  val m:Music = Music()
  m.music.add(5, DummyAdMusic())

  //if the property is not a mutable list, you can convert it to a mutable list
 // or make a copy of it.

  val adapter = Adapter(m)
  recyclerView.adapter = adapter

Now in your adapter, you can do the same thing you're already doing.

The DummyAdMusic class would be a dummy subclass of the MusicItem with null implementation,

 class DummyAdMusic : MusicItem(null,null,...)

You if you don't want to add a custom object to the dataset, you could duplicate the item at position 5:

   m.music.add(5,m.music[5])

** Be sure to check that the list has an index of 5 to avoid an ArrayIndexOutOfBounds Exception.

El Nuru
  • 106
  • 1
  • 6