Notifying an item changed inside a nested adapter - android

I have one ParentAdapter that has multiple view holders and each view holder has its own RecyclerView and an adapter.
I am facing a problem when I need to notify an item of a child adapter is changed. I passed the position of the changed child view holder to the parent and I can use notifyItemChanged(position) but the whole child adapter is recreated.
What I need is to be able to notify a child item and keep the state of the child recyclerview as it is.
Here's the code of the Parent Adapter:
class ParentAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private lateinit var context: Context
private var items = listOf<ParentItem>()
companion object {
const val CHILD_ONE = 1
const val CHILD_TWO = 2
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
context = parent.context
val layoutInflater = LayoutInflater.from(context)
return when(viewType) {
CHILD_ONE -> {
ChildOneViewHolder(layoutInflater.inflate(R.layout.child_one, parent, false))
}
CHILD_TWO -> {
ChildTwoViewHolder(layoutInflater.inflate(R.layout.child_two, parent, false))
}
else -> {
BlankItemViewHolder(layoutInflater.inflate(R.layout.fragment_blank, parent, false))
}
}
}
fun update(items: List<Section>) {
this.items = items
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
val item = items[position]
return when(item.type) {
1 -> CHILD_ONE
2 -> CHILD_TWO
else -> -1
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder.itemViewType) {
CHILD_ONE -> {
val section = items[position]
val childOneAdapter = ChildOneAdapter(this)
if(!section.items.isNullOrEmpty()) {
holder.rvChildOne.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
adapter = childOneAdapter
isNestedScrollingEnabled = true
}
childOneAdapter.update(section.items)
}
}
CHILD_TWO -> {
val section = items[position]
val childTwoAdapter = ChildTwoAdapter(this)
if(!section.items.isNullOrEmpty()) {
holder.rvChildTwo.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
adapter = childTwoAdapter
isNestedScrollingEnabled = true
}
childTwoAdapter.update(section.items)
}
}
else ->
initBlankSection(holder as BlankItemViewHolder, position)
}
}
private fun initBlankSection(holder: BlankItemViewHolder, position: Int) {
}
private class ChildOneViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val rvChildOne: RecyclerView = itemView.findViewById(R.id.rv_child_one)
}
private class ChildTwoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val rvChildTwo: RecyclerView = itemView.findViewById(R.id.rv_child_two)
}
private class BlankItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {}
override fun getItemCount(): Int = items.size
}

Related

Recyclerview with multiple items types not being displayed

I am trying to show multiple type of views in a recyclerview with a header and 5 rows followed by another header and 5 rows but only 4 rows are appearing.
Here is the log output from the adapter in the onBindViewHolder
Here is the code from the adapter
class DailyFragAdapter(
private val activityData: (DetailActivityData) -> Unit,
private val dates: List<Date>,
private val list : ArrayList<TabType1>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>()
/*
ListAdapter<TabType1, RecyclerView.ViewHolder>(Diff())*/ {
private lateinit var context: Context
private val HEADER = 1
private val ROW = 2
/*private class Diff : DiffUtil.ItemCallback<TabType1>() {
override fun areItemsTheSame(oldItem: TabType1, newItem: TabType1): Boolean {
return oldItem.header == newItem.header && oldItem.cps.cps[0].id == newItem.cps.cps[0].id
}
override fun areContentsTheSame(
oldItem: TabType1,
newItem: TabType1
): Boolean {
return oldItem.hashCode() == newItem.hashCode()
}
}*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
context = parent.context
val layoutInflater = LayoutInflater.from(context)
return if (viewType == 2) {
DVH(DailyFragRecyclerItemBinding.inflate(layoutInflater, parent, false))
} else {
TitleHolder(DailyTableHeaderBinding.inflate(layoutInflater, parent, false))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val data: TabType1 = list[position]
if (holder is DVH) {
data.cps.cps.forEach {
Timber.i("is: a row")
holder.bind(it)
}
}else{
Timber.i("is: header")
holder as TitleHolder
holder.bind(data.header)
}
}
override fun getItemViewType(position: Int): Int {
val tabType1 = list[position]
return if (tabType1.header.title == "") {
ROW
} else {
HEADER
}
}
inner class TitleHolder(binding: DailyTableHeaderBinding) :
RecyclerView.ViewHolder(binding.root) {
private val groupHeader: TextView = binding.title
fun bind(title: Header) {
groupHeader.text = title.title
}
}
inner class DVH(binding: DailyFragRecyclerItemBinding) : RecyclerView.ViewHolder(binding.root) {
private var cpname: TextView = binding.cpName
private var day1: FrameLayout = binding.frameLayout
private var day2: FrameLayout = binding.frameLayout2
private var day3: FrameLayout = binding.frameLayout3
private var day4: FrameLayout = binding.frameLayout4
private var dayContainer: ArrayList<FrameLayout> = ArrayList()
fun bind(cpVo: CheckingPointVo) {
dayContainer.addAll(arrayListOf(day1, day2, day3, day4))
cpname.apply {
text = cpVo.name
setOnClickListener {
activityData.invoke(DetailActivityData(cpVo.id, cpVo.pcID))
}
}
val map = cpVo.chartEntriesMap
for (i in dates.indices) {
val dateID = BkpDateUtil.getDateId(dates[i])
Timber.i("dateID $dateID")
var ceVo: List<ChartEntryVo>? = map[dateID]
if (ceVo == null) {
ceVo = ArrayList<ChartEntryVo>()
ceVo.add(ChartEntryVo(0, dateID, 0L, 0L, "", false))
}
val entryValue = ceVo[0].value
when (cpVo.cpType) {
CheckingPointType.YES_NO -> {
val fl: FrameLayout = dayContainer[i]
fl.setOnClickListener {
openYesNoDialog(cpVo, ceVo[0])
}
if (entryValue == 1L) {
setIconInChartEntry(fl, R.drawable.ic_tick, cpVo)
} else {
setIconInChartEntry(fl, R.drawable.ic_no_entry, cpVo)
}
}
CheckingPointType.QUANTIFIABLE -> {
}
CheckingPointType.COUNTABLE -> {
}
CheckingPointType.CATEGORY -> {
}
CheckingPointType.TEXT -> {
}
}
}
dayContainer.clear()
}
}
private fun setIconInChartEntry(fl: FrameLayout, resID: Int, cpVo: CheckingPointVo) {
fl.getChildAt(0).visibility = GONE
val image: ImageView = fl.getChildAt(1) as ImageView
image.visibility = VISIBLE
image.setImageResource(resID)
/*image.setOnClickListener {
activityData.invoke(DetailActivityData(cpVo.id, cpVo.pcID))
}*/
}
private fun openYesNoDialog(cpVo: CheckingPointVo, ce: ChartEntryVo) {
val builder = AlertDialog.Builder(context)
val dataSourceArray = BkpUiUtil.getYesNoArray()
val date = getDateFromId(ce.dateKey)
val title: String = getDayText(date, 1) + " - " + cpVo.name
builder.setTitle(title)
builder.setSingleChoiceItems(
dataSourceArray, BkpUiUtil.getYesNoIndex(ce.value.toString())
) { dialog, which ->
ce.value = BkpUiUtil.getYesNoId(which)
activityData.invoke(
DetailActivityData(
cpvo = cpVo,
cevo = ce,updateChart = true
))
dialog.dismiss()
}
val d = builder.create()
d.show()
}
override fun getItemCount() = list.size
}
data class DetailActivityData(var cpID: Long = 0, var pcID: Long = 0, var cpvo:CheckingPointVo = CheckingPointVo(), var cevo:ChartEntryVo= ChartEntryVo(), var updateChart : Boolean = false)
data class TabType1(
val header: Header = Header(""), val cps: CheckingPointVoList = CheckingPointVoList(
cps = listOf(
CheckingPointVo()
)
)
)
This is how the adapter is given the data.
val data: ArrayList<TabType1> = arrayListOf(
TabType1(
header = Header("Group One")
),
TabType1(
cps = CheckingPointVoList(it)
),
TabType1(
header = Header("Group Two")
),
TabType1(
cps = CheckingPointVoList(it)
)
)
if(it1.updateChart){
vm.updateChartEntry(it1.cpvo,it1.cevo)
}else{
Intent(requireContext(), CpDetailActivity::class.java).apply {
putExtra("cprId", it1.cpID)
putExtra("pcId", it1.pcID)
requireActivity().startActivity(this)
}
}
}, arraylist,dayslist)
This is the output that I get.
What am I missing?
An Adapter should adapt ONE list of data, not multiple lists nested within others. Meaning you need an Adapter and RecyclerView for each list.
If you want to do that you need to add an Adapter/RecyclerView to DVH and display your CheckingPoint list in there.
look here ->
override fun getItemCount() = list.size
Its only going to bind 4 times because you only gave it 4 items.
And here you are just rebinding the same ViewHolder, you need to pass in the data to the ViewHolder and have it display the list of "cps"
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val data: TabType1 = list[position]
if (holder is DVH) {
holder.bind(data) //HERE
}else{
Timber.i("is: header")
holder as TitleHolder
holder.bind(data.header)
}
}
inner class DVH(binding: DailyFragRecyclerItemBinding) : RecyclerView.ViewHolder(binding.root) {
private var checkingPointVoRecyclerView: RecyclerView = binding.recyclerVew
private var checkingPointVoAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> = CheckingPointVoAdapter(dates)
checkingPointVoRecyclerView.adapter = checkingPointVoAdapter
fun bind(data: TabType1) {
checkingPointVoAdapter.list = data.cps
checkingPointVoAdapter.notifyDataSetChanged()
}
}
class CheckingPointVoAdapter(
private val dates: List<Date>,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
public var list: List<CheckingPointVo> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
context = parent.context
val layoutInflater = LayoutInflater.from(context)
return ViewHolder(CheckingPointRecyclerItemBinding.inflate(layoutInflater, parent, false))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val cpv: CheckingPointVo = list[position]
holder as ViewHolder
holder.bind(cpv)
}
inner class ViewHolder(binding: CheckingPointRecyclerItemBinding) : RecyclerView.ViewHolder(binding.root) {
private var cpname: TextView = binding.cpName
private var day1: FrameLayout = binding.frameLayout
private var day2: FrameLayout = binding.frameLayout2
private var day3: FrameLayout = binding.frameLayout3
private var day4: FrameLayout = binding.frameLayout4
private var dayContainer: ArrayList<FrameLayout> = ArrayList()
fun bind(cpVo: CheckingPointVo) {
dayContainer.addAll(arrayListOf(day1, day2, day3, day4))
cpname.apply {
text = cpVo.name
setOnClickListener {
activityData.invoke(DetailActivityData(cpVo.id, cpVo.pcID))
}
}
val map = cpVo.chartEntriesMap
for (i in dates.indices) {
val dateID = BkpDateUtil.getDateId(dates[i])
Timber.i("dateID $dateID")
var ceVo: List<ChartEntryVo>? = map[dateID]
if (ceVo == null) {
ceVo = ArrayList<ChartEntryVo>()
ceVo.add(ChartEntryVo(0, dateID, 0L, 0L, "", false))
}
val entryValue = ceVo[0].value
when (cpVo.cpType) {
CheckingPointType.YES_NO -> {
val fl: FrameLayout = dayContainer[i]
fl.setOnClickListener {
openYesNoDialog(cpVo, ceVo[0])
}
if (entryValue == 1L) {
setIconInChartEntry(fl, R.drawable.ic_tick, cpVo)
} else {
setIconInChartEntry(fl, R.drawable.ic_no_entry, cpVo)
}
}
CheckingPointType.QUANTIFIABLE -> {
}
CheckingPointType.COUNTABLE -> {
}
CheckingPointType.CATEGORY -> {
}
CheckingPointType.TEXT -> {
}
}
}
dayContainer.clear()
}
}
}
I did not test this but this is like 90% of what you need.
OnBindViewHolder gives you a view or you can imagine it as a row
, then you bind data to that row (setting text, etc..)
let's look at what you actually did in OnBindViewHolder
data.cps.cps.forEach { // you bind the data to the same row multiple times
Timber.i("is: a row")
holder.bind(it)
}
But there is only one row.
To solve this you need to pass a list of header items and row items only
sealed class DataItem {
abstract val id: Long
data class RowItem(val row: Row) : DataItem() {
override val id = row.id
}
data class HeaderItem(val header: Header) : DataItem() {
override val id = header.id
}
}
The Transform your row and header data to the DataItem Like this
val rowItems: List<DataItem> = rowList.map { DataItem.RowItem(it) }
val headertems: List<DataItem> = headerList.map { DataItem.BankItem(it) }
val items = rowItems+ headertems
//then pass the items to the adapter
So your adapter now will create a new ViewHoler to each item in the list and you can check for it as
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ITEM_VIEW_TYPE_ITEM_ROW -> DVH(DailyFragRecyclerItemBinding.inflate(layoutInflater, parent, false))
ITEM_VIEW_TYPE_ITEM_HEADER -> TitleHolder(DailyTableHeaderBinding.inflate(layoutInflater, parent, false))
else -> throw ClassCastException("Unknown viewType $viewType")
}
}
then bind data to each view as
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is DVH-> {
val item = getItem(position) as DataItem.RowItem
holder.bind(item)
}
is TitleHolder -> holder.bind(item)
}
}
Finally you need to adjust getItemViewType
override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is DataItem.RowItem -> ITEM_VIEW_TYPE_ITEM_ROW
is DataItem.HeaderItem -> ITEM_VIEW_TYPE_ITEM_HEADER
}
}

Expand/Collapse groups RecyclerView header

I'm trying to create a RecyclerView adapter with two types of items. First one is Header, second one is child item. And when user tap on Header item it will expand child items. Next tap will collapse current section of items. But when I tap on Header in my RecyclerView it shows expanded items after second header. I don't know how to fix it
class SectionedAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var items = mutableListOf<ListItem>()
fun setItems(items: MutableList<ListItem>) {
this.items = items
notifyDataSetChanged()
}
class HeaderItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: HeaderItem) = with(itemView) {
textViewHeader.text = item.title
}
}
class TextItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: TextItem) = with(itemView) {
textViewTitle.text = item.title
textViewContent.text = item.content
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType) {
TYPE_HEADER -> {
val headerView = LayoutInflater.from(parent.context).inflate(R.layout.item_header, parent, false)
return HeaderItemViewHolder(headerView)
}
TYPE_TEXT -> {
val textView = LayoutInflater.from(parent.context).inflate(R.layout.item_text, parent, false)
return TextItemViewHolder(textView)
}
else -> throw IllegalArgumentException()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position]
when(holder) {
is HeaderItemViewHolder -> {
holder.bind(item as HeaderItem)
holder.itemView.setOnClickListener {
if(item.expanded) {
items.addAll(item.items)
notifyItemRangeInserted(position, item.items.size)
}
else {
items.removeAll(item.items)
notifyItemRangeRemoved(position, item.items.size)
}
item.expanded = !item.expanded
}
}
is TextItemViewHolder -> {
holder.bind(item as TextItem)
}
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int {
return items.count()
}
override fun getItemViewType(position: Int): Int {
val item = items[position]
return when(item) {
is HeaderItem -> TYPE_HEADER
is TextItem -> TYPE_TEXT
else -> throw IllegalArgumentException()
}
}
companion object {
const val TYPE_HEADER = 0
const val TYPE_TEXT = 1
}
}
I think what you are trying to achieve would be easier to do with nested Recyclerviews.
In your item_header.xml add a recyclerview, in onBindViewHolder, initialize this subRecyclerView for every sublist, initialize its adapter etc, populate this sub recyclerview with your required items, and let your onclick listener expand / collapse this sub recyclerView by setting its visibility to View.GONE (parent views layout height needs to be set to wrap_content for this to work)

What is a better way to switch between Grid and Linear of RecyclerView with MVVM?

I have a RecyclerView and a FAB in a Fragment.
The FAB switches the layout of the RecyclerView between GRID and LINEAR.
I have a enum class in the ViewModel.
enum class LAYOUT { GRID, LINEAR }
private val _layout = MutableLiveData<LAYOUT>()
val layout: LiveData<LAYOUT>
get() = _layout
And the fragment observes the MutableLiveData of the layout value in ViewModel.
I now kind of get it working by having 2 ListAdapter, one for Grid and one for Linear.
Below is my code of the Fragment.
val gridAdapter = MovieGridAdapter()
viewModel.layout.observe(viewLifecycleOwner, Observer {
if (it == GRID) {
binding.recyclerViewMovie.adapter = gridAdapter
binding.recyclerViewMovie.layoutManager = GridLayoutManager(context, 3)
} else {
binding.recyclerViewMovie.adapter = linearAdapter
binding.recyclerViewMovie.layoutManager = LinearLayoutManager(context)
}
})
viewModel.trendingMovies.observe(viewLifecycleOwner, Observer {
it?.let {
gridAdapter.submitList(it)
linearAdapter.submitList(it)
}
})
I feel like this is not the best way to do it, as I now have 2 adapters in the fragment, and I need to submitList for both adapters.
Please let me know if there is a better way to do this, thanks!
You don't need to use two adapters one adapter can do the work
class ProductListAdapter(
private val listener: OnProductListener) : PagedListAdapter<Product, ProductViewHolder>( PRODUCT_COMPARATOR ) {
var layoutId: Int = R.layout.list_item_product
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val product = getItem(position)
with(holder) {
bindTo(product,true)
product.let { product ->
itemView.setOnClickListener {
product.product_id?.let { it1 -> listener.onProductSelected(it1) }
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val view =
LayoutInflater.from(parent.context)
.inflate(layoutId, parent, false)
return ProductViewHolder(view)
}
override fun getItemViewType(position: Int): Int {
return position
}
fun setLayoutResourceId(layoutId: Int) {
this.layoutId = layoutId
}
companion object {
private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(oldItem: Product, newItem: Product): Boolean =
TextUtils.equals(
oldItem.product_id,
newItem.product_id
)
override fun areContentsTheSame(
oldItem: Product,
newItem: Product
): Boolean =
oldItem == newItem
}
}
}
in you fragment define the adapter
private var productsAdapter: ProductListAdapter = ProductListAdapter(this)
viewModel.trendingMovies.observe(viewLifecycleOwner, Observer {
it?.let {
productsAdapter.submitList(it)
}
})
showList
private fun showList() {
rv_products.layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
productsAdapter.setLayoutResourceId(R.layout.list_item_list_product)
rv_products.adapter = productsAdapter
}
showGrid
private fun showGrid() {
rv_products.layoutManager = GridLayoutManager(activity, 3)
productsAdapter.setLayoutResourceId(R.layout.list_item_grid_product)
rv_products.adapter = productsAdapter
}

Setting RecyclerView adapter into ViewPager2

I've created a RecyclerView with Horizontal Scrolling and PageSnapHelper. Now I think to replace RecyclerView with ViewPager2.? Can I simply set RecyclerView Adapter I've created earlier for new ViewPager2.?
Adapter Class goes here
class QuoteAdapter(
val context: Context,
val list: ArrayList<ResultsItem>
) : RecyclerView.Adapter<QuoteAdapter.QuoteViewHolder>() {
var i = 0;
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
QuoteViewHolder {
val view = LayoutInflater.from(context)
.inflate(R.layout.item_quote, parent, false)
return QuoteViewHolder(view)
}
override fun getItemCount() = list.size
override fun onBindViewHolder(holder: QuoteViewHolder, position: Int) {
holder.quote.text = list[position].quoteText
holder.quote_by.text = "- ${list[position].quoteAuthor}"
ColorStore()
if (position == 0) {
holder.quote_bg.setBackgroundColor(ContextCompat.getColor(context, R.color.md_blue_400))
} else {
holder.quote_bg.setBackgroundColor(ContextCompat.getColor(context, colorList.random()))
}
holder.quote_bg.setOnClickListener {
holder.quote_bg.setBackgroundColor(ContextCompat.getColor(context, colorList.random()))
}
}
class QuoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val quote = itemView.quote_text
val quote_by = itemView.by_text
val quote_bg = itemView.quote_bg
}
}
I just set recyclerview adapter to viewpager2. It works.

How to show single item selected in recyclerview using kotlin

How can we mark single item is selected in Recyclerview using kotlin. When I select an item and after that click on other item then previously selected item should be dis-selected.Here is my adapter class in kotlin:..
class ListAdapter(var context: Context, var list: ArrayList<ListModel>) : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyViewHolder {
val v = LayoutInflater.from(parent?.context).inflate(R.layout.list_item, parent, false)
return MyViewHolder(v)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {
holder?.bindItems(list[position])
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){
fun bindItems(items: ListModel) {
itemView.txt_que.text = items.que
itemView.txt_ans.text = items.ans
itemView.txt_sr_no.text = items.srNo
}
}`
Here dataItem is Model Class and please take one extra Boolean variable isSelected in model class (default value is false) and true when select item then true this variable on selected position,
below are example :
class AllModuleListAdapter(
var context: Context?,
private var moduleList: ArrayList<DataItem?>?,
private var mCallback: DeviceClickListener
) :
RecyclerView.Adapter<AllModuleListAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val context = parent.context
val itemView = LayoutInflater.from(context).inflate(R.layout.item_modules, parent, false)
return MyViewHolder(itemView)
}
override fun getItemCount(): Int {
return moduleList?.size ?: 0
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(moduleList?.get(position))
if (moduleList?.get(position) is DataItem) {
val dataItem = moduleList?.get(position) as DataItem
if (dataItem.isSelected) {
context?.let { ContextCompat.getColor(it, R.color.colorOrange) }
?.let { holder.itemView.setBackgroundColor(it) }
} else {
context?.let { ContextCompat.getColor(it, R.color.white) }
?.let { holder.itemView.setBackgroundColor(it) }
}
}
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.constraint_main.setOnClickListener {
val list = moduleList as List<DataItem>
for (item in list.indices) {
list[item].isSelected = false
}
list[adapterPosition].isSelected = true
mCallback.onDeviceClick(adapterPosition)
notifyDataSetChanged()
context?.let { it1 -> ContextCompat.getColor(it1, R.color.colorOrange) }?.let { it2 ->
itemView.constraint_main?.setBackgroundColor(it2)
}
}
}
fun bind(module: DataItem?) {
itemView.txtModuleName?.text = module?.id.toString()
itemView.txtSignal?.text = module?.room
}
}
}
if (mPosition == position)
{
//set selected here
} else
{
//set unselected here
}
holder.parentView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
mPosition = position;
notifyDataSetChanged();
}
});
Write above code in onBindViewholder and declare mPosition as global int variable in adapter class
Try with this:- take one variable in your ListModel class as
var selected:boolean = false
then while setting the listModel items set this value as false as
for(int i=0;i<listModel.size;i++){
listModel.get(i).selected = false
}//this is for setting all values false
when you select any item from list call this method and then set selected = true for selected position and simply refresh the adapter list.
in your adapter check for this selected value and accordingly set the check box value inside your bindItems method
itemView.checkBox.selected = items.selected//this will set your checkbox selected value

Categories

Resources