so i'm trying to do connection between 2 ListViews, after clicking on 1 item in first ListView, it changes an Array (depending on what i've cliked), that Array goes as a constructor to the second ListView, which changes background depending on what is in array, which means: I click on button in 1. ListView, 2. ListView react (in this sample changes background). I found something called "notifyDataSetChanged", but that didn't help me at all, tried to make a update method in second ListView as well, neither that worked out. Appreciate any help, thanks
class ChoosingSpells : AppCompatActivity() {
private var learnedSpells = listOf(3,4,0,0,5,5)
private val chosenSpells = arrayOf(5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
private var clickedSpell = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_choosing_spells)
buttonChoose.visibility = View.INVISIBLE
val listView = findViewById<ListView>(R.id.choosing_listview)
choosing_listview.adapter = LearnedSpellsView(textLabel,textLevel,textDescription,textStats, learnedSpells, clickedSpell, buttonChoose)
chosen_listView.adapter = ChosenSpellsView(chosenSpells)
buttonChoose.setOnClickListener{
for (i in 1..19) {
if(chosenSpells[i] != 0){
chosenSpells[i] = clickedSpell
buttonChoose.text = chosenSpells[i].toString()
break
}
}
}
}
private class LearnedSpellsView(var textViewLabel: TextView, var textViewLevel: TextView, var textViewDescription: TextView, var textViewStats: TextView, val learnedSpells: List<Int>, var clickedSpell:Int, var buttonChoose: Button) : BaseAdapter() {
override fun getCount(): Int {
return (learnedSpells.size/2+1)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItem(position: Int): Any {
return "TEST STRING"
}
override fun getView(position: Int, convertView: View?, viewGroup: ViewGroup?): View {
val rowMain: View
if (convertView == null) {
val layoutInflater = LayoutInflater.from(viewGroup!!.context)
rowMain = layoutInflater.inflate(R.layout.row_choosingspells, viewGroup, false)
val viewHolder = ViewHolder(rowMain.button1, rowMain.button2)
rowMain.tag = viewHolder
} else {
rowMain = convertView
}
val viewHolder = rowMain.tag as ViewHolder
try{
viewHolder.button1.setBackgroundResource(getDrawable(learnedSpells[if(position==0){0}else{position*2}]))
viewHolder.button2.setBackgroundResource(getDrawable(learnedSpells[if(position==0){1}else{position*2+1}]))
if(learnedSpells[if(position==0){0}else{position*2}]!=0){
viewHolder.button1.setOnClickListener {
textViewLabel.text = spellSpec(learnedSpells[if(position==0){0}else{position*2}],0)
textViewLevel.text = spellSpec(learnedSpells[if(position==0){0}else{position*2}],3)
textViewStats.text = spellSpec(learnedSpells[if(position==0){0}else{position*2}],2)
textViewDescription.text = spellSpec(learnedSpells[if(position==0){0}else{position*2}],4)
clickedSpell = learnedSpells[if(position==0){0}else{position*2}]
buttonChoose.visibility = View.VISIBLE
}
}else{
viewHolder.button1.isClickable = false
}
}catch(e:Exception){
viewHolder.button1.isClickable = false
viewHolder.button1.setBackgroundResource(getDrawable(0))
}
try{
if(learnedSpells[if(position==0){1}else{position*2+1}]!=0){
viewHolder.button2.setOnClickListener {
textViewLabel.text = spellSpec(learnedSpells[if(position==0){1}else{position*2+1}],0)
textViewLevel.text = spellSpec(learnedSpells[if(position==0){1}else{position*2+1}],3)
textViewStats.text = spellSpec(learnedSpells[if(position==0){1}else{position*2+1}],2)
textViewDescription.text = spellSpec(learnedSpells[if(position==0){1}else{position*2+1}],4)
clickedSpell = learnedSpells[if(position==0){1}else{position*2+1}]
buttonChoose.visibility = View.VISIBLE
}
}else{
viewHolder.button2.isClickable = false
}
}catch(e:Exception){
viewHolder.button2.isClickable = false
viewHolder.button2.setBackgroundResource(getDrawable(0))
}
return rowMain
}
private fun getDrawable(index:Int): Int {
return(when(index) {
3 -> R.drawable.firespell
4 -> R.drawable.icespell
5 -> R.drawable.windspell
0 -> R.drawable.shield
else -> NULL
}
)
}
private class ViewHolder(val button1: TextView, val button2: TextView)
}
private class ChosenSpellsView(var chosenSpells: Array<Int>) : BaseAdapter() {
override fun getCount(): Int {
return 20
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItem(position: Int): Any {
return "TEST STRING"
}
fun updateAdapter(chsenSpells: Array<Int>) {
this.chosenSpells = chsenSpells
notifyDataSetChanged()
}
override fun getView(position: Int, convertView: View?, viewGroup: ViewGroup?): View {
val rowMain: View
if (convertView == null) {
val layoutInflater = LayoutInflater.from(viewGroup!!.context)
rowMain = layoutInflater.inflate(R.layout.row_chosen_spells, viewGroup, false)
val viewHolder = ViewHolder(rowMain.button1)
rowMain.tag = viewHolder
} else {
rowMain = convertView
}
val viewHolder = rowMain.tag as ViewHolder
viewHolder.button1.setBackgroundResource(getDrawable(chosenSpells[position]))
viewHolder.button1.text = (position+1).toString()
viewHolder.button1.gravity = Gravity.LEFT;
viewHolder.button1.setOnClickListener {
chosenSpells[position] = 0
viewHolder.button1.setBackgroundResource(getDrawable(chosenSpells[position]))
}
return rowMain
}
private fun getDrawable(index:Int): Int {
return(when(index) {
3 -> R.drawable.firespell
4 -> R.drawable.icespell
5 -> R.drawable.windspell
0 -> R.drawable.shield //empty slot
else -> NULL
}
)
}
private class ViewHolder(val button1: TextView)
}
}
Used notifyDataSetChanged() out of the Adapter and works well.
Related
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
}
}
In my app I have some fragments and I switch between them with this nice animation:
activity?.supportFragmentManager?.beginTransaction()
?.setCustomAnimations(
R.anim.slide_in_from_right,
R.anim.slide_out_to_left,
R.anim.slide_in_from_left,
R.anim.slide_out_to_right)
?.replace(R.id.fragmentContainer, articleContentFragment)
?.addToBackStack(null)
?.commit()
Inside of every fragment I have a RecyclerView with several types of items e.g. TextViews or ImageViews.
And it works fine, but
when I added a WebView as one of the types of my RecyclerView items, nice animation of fragment transaction started to freeze the first time I open the fragment. The cause is inflating of WebView.
How can I inflate view in background thread or maybe there are any better solutions?
(It still works fine in RecyclerViews, which do not inflate WebView as an item)
My Adapter:
class ArticleContentAdapter(
context: Context
) : RecyclerView.Adapter<ArticleContentAdapter.BaseViewHolder<*>>() {
companion object {
private const val headerType = 1
private const val paragraphType = 2
private const val codeSnippetType = 3
private const val imageType = 4
}
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var articlePieces = ArrayList<ArticlePiece>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<*> {
return when (viewType) {
headerType -> ArticleHeaderViewHolder(
inflater.inflate(
R.layout.article_header_item,
parent,
false
)
)
paragraphType -> ArticleParagraphViewHolder(
inflater.inflate(
R.layout.article_paragraph_item,
parent,
false
)
)
codeSnippetType -> ArticleCodeSnippetViewHolder(
inflater.inflate(
R.layout.article_code_snippet_item,
parent,
false
)
)
imageType -> ArticleImageViewHolder(
inflater.inflate(
R.layout.article_image_item,
parent,
false
)
)
else -> throw IllegalArgumentException("Invalid view type.")
}
}
override fun getItemViewType(position: Int): Int {
return when (articlePieces[position]) {
is ArticleHeader -> headerType
is ArticleParagraph -> paragraphType
is ArticleCodeSnippet -> codeSnippetType
is ArticleImage -> imageType
else -> throw IllegalArgumentException("Invalid type of data $position.")
}
}
override fun getItemCount() = articlePieces.size
internal fun addArticlePieces(articlePieces: List<ArticlePiece>) {
this.articlePieces = getAllSortedPieces(this.articlePieces, articlePieces)
notifyDataSetChanged()
}
private fun getAllSortedPieces(
formerPieces: List<ArticlePiece>,
newPieces: List<ArticlePiece>
): ArrayList<ArticlePiece> {
val allSortedPieces = ArrayList<ArticlePiece>()
allSortedPieces.addAll(formerPieces)
allSortedPieces.addAll(newPieces)
allSortedPieces.sortBy { A -> A.positionInArticle }
return allSortedPieces
}
abstract class BaseViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(item: T)
}
class ArticleHeaderViewHolder(itemView: View) :
BaseViewHolder<ArticleHeader>(itemView) {
private val articleHeader: TextView = itemView.header
override fun bind(item: ArticleHeader) {
articleHeader.text = item.getEssentialDataOfPiece()
}
}
class ArticleParagraphViewHolder(itemView: View) :
BaseViewHolder<ArticleParagraph>(itemView) {
private val articleParagraph: TextView = itemView.paragraph
override fun bind(item: ArticleParagraph) {
val text = "\t ${item.getEssentialDataOfPiece()}"
articleParagraph.text = text
}
}
class ArticleCodeSnippetViewHolder(itemView: View) :
BaseViewHolder<ArticleCodeSnippet>(itemView) {
private val webView: WebView = itemView.webView
private val loadingPlaceholder: LinearLayout = itemView.loadingPlaceholder
private val noInternetConnectionPlaceholder: LinearLayout =
itemView.noInternetConnectionPlaceholder
override fun bind(item: ArticleCodeSnippet) {
val codeSnippetController = CodeSnippetController(
item,
webView,
loadingPlaceholder,
noInternetConnectionPlaceholder
)
if (item.viewHeight != 0 || item.viewHeight != 1) {
webView.layoutParams.height = item.viewHeight
loadingPlaceholder.layoutParams.height = item.viewHeight
noInternetConnectionPlaceholder.layoutParams.height = item.viewHeight
}
codeSnippetController.loadCodeSnippet()
}
}
class ArticleImageViewHolder(itemView: View) :
BaseViewHolder<ArticleImage>(itemView) {
private val imageView: ImageView = itemView.imageView
// private val loadingPlaceholder: LinearLayout = itemView.loadingPlaceholder
// private val noInternetConnectionPlaceholder: LinearLayout =
// itemView.noInternetConnectionPlaceholder
override fun bind(item: ArticleImage) {
Picasso.get().load(item.url).into(imageView)
}
}
override fun onBindViewHolder(holder: BaseViewHolder<*>, position: Int) {
val piece = articlePieces[position]
when (holder) {
is ArticleHeaderViewHolder -> holder.bind(piece as ArticleHeader)
is ArticleParagraphViewHolder -> holder.bind(piece as ArticleParagraph)
is ArticleCodeSnippetViewHolder -> holder.bind(piece as ArticleCodeSnippet)
is ArticleImageViewHolder -> holder.bind(piece as ArticleImage)
else -> throw IllegalArgumentException()
}
}
}
There are two Recyclerview in same activity rv1 and rv2. Selected item of rv1 will show in rv2
rv1:
Here I select multiple items
rv2:
it should shows like this
Adapter class of rv1:
class ServiceJobAdapter(val context: Context, var list:ArrayList<JobRespo>,var listener:OnItemClick):
RecyclerView.Adapter<ServiceJobAdapter.ItemsCarrier>(){
var currentSelectedIndex= -1
var selectedItem = SparseBooleanArray()
var animationItemsIndex = SparseBooleanArray()
private val reverseAllAnimations = false
var holder:ItemsCarrier? =null
class ItemsCarrier(itemView: View) : RecyclerView.ViewHolder(itemView)
{
var jobName = itemView.findViewById<TextView>(R.id.job_name)
var jobPrice = itemView.findViewById<TextView>(R.id.job_price)
var iconBack = itemView.findViewById(R.id.icon_back) as RelativeLayout
var iconFront = itemView.findViewById(R.id.icon_front) as RelativeLayout
var iconContainer = itemView.findViewById(R.id.icon_container) as CardView
fun binde(jobRespo: JobRespo) {
jobName.text = jobRespo.repDesc
jobPrice.text="₹"+jobRespo.repRice
if (iconFront.visibility == View.VISIBLE)
{
jobRespo.setChecked(false)
}else{
jobRespo.setChecked(true)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemsCarrier {
val view = LayoutInflater.from(context).inflate(R.layout.job_row,parent,false)
return ItemsCarrier(view)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ItemsCarrier, position: Int) {
this.holder = holder
holder.itemView.isActivated = selectedItem[position,false]
holder.binde(list[position])
applyIconAnimation(holder, position)
// apply click events
applyClickEvents(holder, position)
}
private fun applyClickEvents(holder: ItemsCarrier, position: Int) {
holder.iconContainer.setOnClickListener {
listener.onIconClicked(position)
listener.AllItem(list[position]) }
}
private fun applyIconAnimation(holder: ItemsCarrier, position: Int)
{
if (selectedItem.get(position, false)) {
holder.iconFront!!.visibility = View.GONE
resetIconYAxis(holder.iconBack)
holder.iconBack.visibility = View.VISIBLE
holder.iconBack.alpha = 1f
if (currentSelectedIndex == position) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, true)
resetCurrentIndex()
}
} else {
holder.iconBack.visibility = View.GONE
resetIconYAxis(holder.iconFront)
holder.iconFront.visibility = View.VISIBLE
holder.iconFront.alpha = 1f
if (reverseAllAnimations && animationItemsIndex.get(
position,
false
) || currentSelectedIndex == position
) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, false)
resetCurrentIndex() } } }
private fun resetIconYAxis(view: RelativeLayout?)
{
if (view!!.rotationY != 0f) {
view.rotationY = 0f
}
}
private fun resetCurrentIndex() {
currentSelectedIndex = -1
}
fun toggleSelection(pos: Int) {
currentSelectedIndex = pos
if (selectedItem.get(pos, false)) {
selectedItem.delete(pos)
animationItemsIndex.delete(pos)
} else {
selectedItem.put(pos, true)
animationItemsIndex.put(pos, true)
}
notifyItemChanged(pos)
}
fun getSelectedItems(): ArrayList<JobRespo>
{
val selectItems = ArrayList<JobRespo>()
for(item in list)
{
if (!item.isChecked())
{
selectItems.add(item)
}
}
return selectItems}}
Using Interface
interface OnItemClick{
fun onIconClicked(position: Int)
fun AllItem(jobs:JobRespo)}
Implement interface in Activity
override fun onIconClicked(position: Int) {
mAdapter!!.toggleSelection(position)
}
override fun AllItem(jobs: JobRespo) {
val selectedItems:ArrayList<JobRespo>
=mAdapter!!.getSelectedItems()
selectIte.addAll(selectedItems)
}
Adapter class of 2nd Recyclerview:
lass SelectItemAdapter(val context: Context, var list:List<JobRespo>): RecyclerView.Adapter<SelectItemAdapter.ItemsCarriers>(){
class ItemsCarriers(itemView: View) : RecyclerView.ViewHolder(itemView) {
var itemName = itemView.findViewById<TextView>(R.id.item_name)
var itemPrice= itemView.findViewById<TextView>(R.id.item_peice)
var itmDelet =itemView.findViewById<LinearLayout>(R.id.item_delete)
fun bind(job: JobRespo) {
itemName.text = job.repDesc
itemPrice.text = job.repRice }
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemsCarriers {
val root = LayoutInflater.from(context).inflate(R.layout.select_item_row,parent,false)
return ItemsCarriers(root)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ItemsCarriers, position: Int) {
holder.bind(list[position])}}
Now how can i pass multiselected data from one recyclerview to anathor recyclerview of same activity?
Thanks your consideration and guidded to me :)
You can create a method in a second adapter to update the selected value like below and use it when you getting selected items.
fun setSelectedData(data:ArrayList<JobRespo>){
this.list.clear()
this.list.addAll(data)
notifyDataSetChanged ();
}
Why doesn't my function allow me to set a content description for my ImageView? It seems to allow me to set a drawable resource and text though.
class MyAdapter(
private val dataIVPlayOrPause: Drawable,
private val dataTVSong: String
) : RecyclerView.Adapter<RVAdapterEmbark.MyViewHolder>() {
private val typeHeader = 1
private val typeItem = 2
override fun onCreateViewHolder(parent: ViewGroup, type: Int): MyViewHolder {
return when (type) {
typeHeader -> MyViewHolder(inflateHelper(R.layout.header, parent))
typeItem -> MyViewHolder(inflateHelper(R.layout.body, parent))
else -> MyViewHolder(inflateHelper(R.layout.body, parent))
}
}
override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) {
if (getItemViewType(position) == typeHeader) {
} else if (getItemViewType(position) == typeItem) {
val ivPlayPause = viewHolder.itemView. iv_Play_Pause
ivPlayPause(R.drawable.play)
ivPlayPause = R.string.play.toString()
val buttonClickListener = View.OnClickListener {
if (tvSongName.text == null) {
playSong(tvSongName, ivPlayPause)
} else {
pauseSong(tvSongName, ivPlayPause)
}
}
}
}
private fun inflateHelper(resId: Int, parent: ViewGroup): View {
return LayoutInflater.from(parent.context).inflate(resId, parent, false)
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
override fun getItemCount(): Int {
return dataTitle.size + 1
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) typeHeader
else typeItem
}
private fun playSong(
tvSongName: TextView,
ivPlayPause: ImageView
) {
tvSongName.text = "Song name"
ivPlayPause.setImageResource(R.drawable.pause)
ivPlayPause.contentDescription = getString(R.string.pause)
}
}
Since you are in a RecyclerView.Adapter, you can't access the Activity, Fragment or Context instance in which getString() is declared.
In this case you can use the Context of your ImageView to get the string:
ivPlayPause.contentDescription = ivPlayPause.context.getString(R.string.pause)
I'm trying to get my RecyclerView adapter to obtain values from an Array in my fragment but for some reason is doesn't work and I get this error (I think I have gotten lost somewhere):
lateinit property dataTitles has not been initialized
What's the correct way to obtain the data in this scenario?
Fragment class
class MyFragment : androidx.fragment.app.Fragment() {
private lateinit var mRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_rv, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
val v = view
val dataTitles: ArrayList<String> = ArrayList()
val dataSubtitles: ArrayList<String> = ArrayList()
mRecyclerView = v!!.findViewById<RecyclerView>(R.id.my_recyclerview)
// Set the linear layout manager
mRecyclerView.layoutManager = LinearLayoutManager(activity)
// create the adapter
val mAdapter = MyRVAdapter()
// init data
dataTitles.add(getString(R.string.addition))
dataTitles.add(getString(R.string.subtraction))
dataTitles.add(getString(R.string.multiplication))
dataTitles.add(getString(R.string.division))
dataSubtitles.add(getString(R.string.addition_information))
dataSubtitles.add(getString(R.string.subtraction_information))
dataSubtitles.add(getString(R.string.multiplication_information))
dataSubtitles.add(getString(R.string.division_information))
// Set the adapter
mRecyclerView.adapter = mAdapter
super.onActivityCreated(savedInstanceState)
}
}
Adapter class
class MyRVAdapter(private val dataTitles: Array<String>, private val dataSubtitles: Array<String>): RecyclerView.Adapter<MyRVAdapter.MyViewHolder>() {
private val typeItem = 1
private val typeHeader = 2
private val typeGrid = 3
private val primeNumbers = arrayOf("2", "3", "5", "7", "11", "13",
"17", "19", "23")
private lateinit var adapterGV: MyAdapter
override fun onCreateViewHolder(parent: ViewGroup, type: Int): MyRVAdapter.MyViewHolder {
return when (type) {
typeHeader -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_header, parent))
typeItem -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_item, parent))
typeGrid -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_gv, parent))
else -> MyRVAdapter.MyViewHolder(inflateHelper(R.layout.rv_item, parent))
}
}
override fun onBindViewHolder(viewHolder: MyRVAdapter.MyViewHolder, position: Int) {
val llGV = viewHolder.itemView.findViewById<LinearLayout>(R.id.ll_gv)
val llTV = viewHolder.itemView.findViewById<LinearLayout>(R.id.ll_tv)
val mGridView = viewHolder.itemView.findViewById<GridView>(R.id.my_gv)
when (getItemViewType(position)) {
typeHeader -> {
val tValueE = TypedValue()
// test
llTV.context.theme.resolveAttribute(R.attr.imgUnfoldMore, tValueE, true)
val tValueC = TypedValue()
// test
llTV.context.theme.resolveAttribute(R.attr.imgUnfoldLess, tValueC, true)
}
typeGrid -> {
val titleG = viewHolder.itemView.findViewById<TextView>(R.id.tv_gv_A)
titleG.setText(R.string.prime_numbers)
//
val cardViewGV = viewHolder.itemView.findViewById<CardView>(R.id.cv_gv)
val mLinearLayoutGV = viewHolder.itemView.findViewById<LinearLayout>(R.id.cardview_gv_titlerow
mGridViewA.isEnabled = false
mGridViewA.isVerticalScrollBarEnabled = false
// adapterGV = MyAdapter(activity!!.applicationContext, 0)
mGridViewA.adapter = adapterGV
for (ldnBusesRoute in ldnBusesRoutes) {
adapterGV.addAdapterItem(AdapterItem(ldnBusesRoute))
}
typeItem -> {
// get the current item
val itemA = dataTitles[position - 2]
val itemB = dataSubtitles[position - 2]
//
val txtTitle = viewHolder.itemView.findViewById<TextView>(R.id.tv_title)
txtTitle.text = itemA
val txtSubtitle = viewHolder.itemView.findViewById<TextView>(R.id.tv_subtitle)
txtSubtitle.text = itemB
}
}
}
private fun inflateHelper(resId: Int, parent: ViewGroup): View {
return LayoutInflater.from(parent.context).inflate(resId, parent, false)
}
// inner class for view holder to use,
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
// Adapter for GridView
private inner class MyAdapter internal constructor(context: Context, textviewid: Int) : ArrayAdapter<AdapterItem>(context, textviewid) {
private val items = ArrayList<AdapterItem>()
internal fun addAdapterItem(item: AdapterItem) {
items.add(item)
}
override fun getCount(): Int {
return items.size
}
override fun getItem(position: Int): AdapterItem? {
return items[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val rowView: View = when (convertView) {
null -> LayoutInflater.from(parent.context).inflate(R.layout.gridview_item, parent, false)
// activity!!.layoutInflater.inflate(R.layout.gridview_item, parent, false)
else -> convertView
}
val tv = rowView.findViewById(R.id.item_gridview) as TextView
tv.text = items[position].first
return rowView
}
}
internal inner class AdapterItem // add more items
(var first: String)
override fun getItemCount(): Int {
return dataTitles.size + 2
}
override fun getItemViewType(position: Int): Int {
return when (position) {
0 -> typeHeader
1 -> typeGrid
else -> typeItem
}
}
}
Well, the error is pretty straightforward: you're not initializing dataTitles. When you label a variable with lateinit, Kotlin expects you to initialize it later. It's a way to avoid having to declare the variable as nullable.
To initialize it, you can do something like:
private val mutableList = mutableListOf<String>()
And you're doing the same with dataSubtitles.