androidkotlinandroid-recyclerviewretrofitcardview

Android Studio Kotlin Recyclerview how to do multiple type view for specific object feature?


I have data from RickandMorty Api and saving them on CharacterList and I am showing them in a recyclerview.I have name,location and status informations and showing them in cards.I have another carditem for displaying dead users and I want to show Alive persons in default card and Dead persons in another carditem (Default Carditem with blue backgroundcolor and other carditem is with red backgroundcolor).So as my researches people handle that with getItemViewType() but in my case I want to classify them each object's status type which is Alive or Dead.How can I do it?

Here is my Main Activity class

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    viewModel = ViewModelProviders.of(this).get(CharacterViewModel::class.java)

    CoroutineScope(Dispatchers.IO).launch {
        viewModel.getData()
    }

    viewModel.users.observe(this, Observer { characterList ->
        for (i in characterList.results){
            Log.e(TAG, "${i.name}")
            name_list.add(i.name)
        }
        recyclerview1.layoutManager = LinearLayoutManager(this)
        recyclerview1.adapter = Adapter(characterList.results)


    })


}}

Here is my ViewHolder Class

class ViewHolder (container: ViewGroup) : RecyclerView.ViewHolder(
        //xml deki verilere bakarak arayüz viewvi oluşturuyor
        LayoutInflater.from(container.context).inflate
            (
            R.layout.carditem,
            container,
            false
        )
    ) {
    val crdView: CardView = itemView.findViewById(R.id.cardview1)
    val profileLink: ImageView = itemView.findViewById(R.id.imgProfilePhoto)
    val txtname: TextView = itemView.findViewById(R.id.name)
    val txtlocation: TextView = itemView.findViewById(R.id.location)
    val txtstatus: TextView = itemView.findViewById(R.id.status)


    fun bind(characteritem: Result) {
        txtname.text = characteritem.name
        profileLink.load(characteritem.image)
        txtlocation.text = characteritem.location.name
        txtstatus.text=characteritem.status
    }
}

And my Adapter class

class Adapter(val CharacterList: List<Result>):RecyclerView.Adapter<ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(parent)
    }

    override fun getItemCount(): Int {
        return CharacterList.size
    }

    override fun onBindViewHolder(holder: ViewHolder,position: Int) {
            holder.bind(CharacterList[position])

    }


}

Here is what I've done

And what I am trying to make

The view of Cards


Solution

  • If your different layouts have the same resources, just with different appearance you could just pass an alternate layout ID to your view holder, like this:

    class Adapter(val CharacterList: List<Result>):RecyclerView.Adapter<ViewHolder>() {
    
        override fun getItemViewType(position: Int): Int {
            return if (CharacterList[position].status == "Dead") 0 else 1
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val layout = if(viewType == 0) R.layout.card_dead else R.layout.card_alive
            return ViewHolder(parent, layout)
        }
    
        override fun getItemCount(): Int {
            return CharacterList.size
        }
    
        override fun onBindViewHolder(holder: ViewHolder,position: Int) {
            holder.bind(CharacterList[position])
        }
    }
    

    Then modify the view holder to take the layout ID as a constructor input:

    class ViewHolder (container: ViewGroup, layout: Int) : RecyclerView.ViewHolder(
        LayoutInflater.from(container.context).inflate
            (
                layout,
                container,
                false
            )
        ) 
    {
        //...
    }
    

    Alternately you could just use a single layout and change the background color programmatically in bind