Replace Recyclerview's textview item to imageview item - android

I have RecyclerViewwith TextView items and want to replace the last item to ImageView. The numbers must be text, that's why I can't make all them ImageView
It mmust be like this:
I add TextView and ImageView to recycler row item and make the visibility of ImageView gone. Here is my ViewHolder
override fun onBindViewHolder(holder: TestView, position: Int) {
holder.testName?.text = listOfTests?.get(position)?.testName
holder.txtNumberIcon?.text = listOfTests?.get(position)?.txtNumberIcon
if (listOfTests?.get(listOfTests!!.size.minus(1))?.txtNumberIcon == dont know what condition must be here) {
holder.txtNumberIcon?.visibility = View.GONE
holder.imageStarIcon?.visibility = View.VISIBLE
Glide
.with(context?.applicationContext!!)
.load(listOfTests?.get(listOfTests!!.size.minus(1))?.testNumberIcon)
.into(holder.imageStarIcon!!)
}
What condition I must write to replace last item from textview to imageview?

Let me see if I understand it right.
If the listOfTests has 10 elements you want 9 cells from the RecyclerView to be TextView's and 1 ImageView.
If so:
override fun onBindViewHolder(holder: TestView, position: Int) {
holder.testName?.text = listOfTests?.get(position)?.testName
holder.txtNumberIcon?.text = listOfTests?.get(position)?.txtNumberIcon
if (position == listOfTests.size - 1) { /* position starts from 0 */
// I would suggest to load the image only for the element that will be displayed
Glide.with(context?.applicationContext!!)
.load(listOfTests?.get(position)?.testNumberIcon)
.into(holder.imageStarIcon!!)
holder.txtNumberIcon?.visibility = View.GONE
holder.imageStarIcon?.visibility = View.VISIBLE
}
else {
holder.txtNumberIcon?.visibility = View.VISIBLE
holder.imageStarIcon?.visibility = View.GONE
}
}

Related

My adapter in recyclerview change background color of 2 items instead of 1

I have 10 items like this in recyclerview. My problem is when I click one item I change the background color but for some reason another item changes its background color too. I don't know why this is happening.
For example, if I click the first item and change the color, the item in position 8 also changes its color. I only want the item that I click on to change its color.
This is my code:
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val titulo = holder.itemView.findViewById(R.id.txt_categoria) as TextView
titulo.text = categories[position].name_category!!
holder.itemView.setOnClickListener{
when{
textView == null ->{
textView = holder.itemView.txt_categoria
textView!!.setBackgroundResource(R.drawable.design_categories_project)
textView!!.setTextColor(Color.WHITE)
fragmentProyectos.filterProjects(categories[position].id_categorie!!,
categories[position].name_category!!)
}
posClicked != position ->{
holder.itemView.txt_categoria.setBackgroundResource(R.drawable.design_categories_project)
holder.itemView.txt_categoria.setTextColor(Color.WHITE)
textView!!.setBackgroundResource(R.drawable.design_categories_project_white)
textView!!.setTextColor((Color.parseColor("#343434")))
textView = holder.itemView.txt_categoria
fragmentProyectos.filterProjects(categories[position].id_categorie!!,
categories[position].name_category!!)
}
else ->{
textView!!.setBackgroundResource(R.drawable.design_categories_project_white)
textView!!.setTextColor((Color.parseColor("#343434")))
textView = null
fragmentProyectos.getData()
}
}
posClicked = position
}
}
Try setting the color like this:
titulo.setTextColor((Color.parseColor("#343434")))

Recyclerview adapter onBindViewHolder payload is not working

I checked all the examples, but they don't work after all. As far as I know, even if payload is 'List', String or Int value can go into.
class RecordListAdapter (val context: Context, val layoutManager: LinearLayoutManager, private val canBeEdited: Boolean)
: RecyclerView.Adapter<RecordListAdapter.RecordViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var records: ArrayList<Record> = arrayListOf()
// Update ALL VIEW holder
override fun onBindViewHolder(holder: RecordViewHolder, position: Int) {
val current = records[position]
holder.autoCompleteTextView.text = SpannableStringBuilder(current.name)
holder.weightPicker.value = current.weight
holder.setPicker.value = current.set
holder.repsPicker.value = current.reps
if(position == itemCount - 1) holder.addBtn.visibility = View.VISIBLE
else holder.addBtn.visibility = View.GONE
if(canBeEdited) {
if(itemCount == 1) {
holder.deleteBtn.visibility = View.GONE
} else {
holder.deleteBtn.visibility = View.VISIBLE
holder.deleteBtn.setOnClickListener {
records.remove(current)
notifyItemRemoved(position)
}
}
} else
holder.deleteBtn.visibility = View.GONE
}
// Update only part of ViewHolder that you are interested in
override fun onBindViewHolder(holder: RecordViewHolder, position: Int, payloads: MutableList<Any>) {
Log.e("payload", "::$payloads")
if(payloads.isNotEmpty()) {
} else
super.onBindViewHolder(holder,position, payloads)
}
private fun addRecordDefault() {
this.records.add(Record("", 28, 5, 10))
notifyItemInserted(itemCount)
notifyItemRangeChanged(itemCount-1, 2, "PAYLOAD_ADD_BTN")
}
override fun getItemCount() = records.size
}
As above code, I set the Log.e to know whether the value is empty or not. The payload Log.e always say it's null.
E/payload: ::[]
Firstly, it seems you are just adding the item and want to change something in it with payloads right away.
Obviously, when you just add a new one, the whole item has to be drawn, thus no payloads needed.
Only then, when it is already drawn and you want to change some elements, you may use payloads with notifyItemChanged (if one item was changed) or notifyItemRangeChanged (if several items were changed).
Secondly, I am not sure regarding the range you use.
The first argument of notifyItemRangeChanged is the start index.
The second one is how many items you want to change.
Thirdly, it's not clear where do you call the addRecordDefault
So make sure you called notifyItemChanged or notifyItemRangeChanged with payloads.

Recycler view post Item deletion, has deleted views overlapping other views

I already tried this solution here, but unfortunately doesnt work in my scenario.
Ill keep it simple: I have multiple viewHolders with multiple animations for a chat App,
Since I have no touch listeners to register the adapter position of the typing indicators, I have:
In my CustomAdapter
private var typingIndicatorAdapterPosition: Int = -1
private var inlineErrorAdapterPosition: Int = -1
In my onBindViewHolder
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder.itemViewType) {
...
USER_REQUEST_TEXT -> {
val userRequestViewHolder = (holder as UserRequestViewHolder)
configUserRequestViewHolder(userRequestViewHolder, position)
userRequestViewHolder.setIsRecyclable(false)
}
TYPE_INDICATOR -> {
val typingIndicatorViewHolder = (holder as TypingIndicatorViewHolder)
configTypingIndicatorViewHolder(typingIndicatorViewHolder, position)
typingIndicatorAdapterPosition = typingIndicatorViewHolder.layoutPosition
typingIndicatorViewHolder.setIsRecyclable(true)
}
INLINE_ERROR -> {
val inlineErrorViewHolder = (holder as InlineErrorViewHolder)
configInlineErrorViewHolder(inlineErrorViewHolder, position)
inlineErrorAdapterPosition = inlineErrorViewHolder.layoutPosition
inlineErrorViewHolder.setIsRecyclable(true)
}
}
}
my adapter code for deletion :
fun removeTypingIndicator() {
if(typingIndicatorAdapterPosition > 0) {
if(messageContainerList[typingIndicatorAdapterPosition].messageType == TYPE_INDICATOR) {
messageContainerList.removeAt(typingIndicatorAdapterPosition)
notifyItemRemoved(typingIndicatorAdapterPosition)
notifyItemRangeChanged(typingIndicatorAdapterPosition, itemCount - 1)
typingIndicatorAdapterPosition = -1
}
}
}
Note - I do not prefer notifyDataSetChanged() etc. as it cancels the animations.
here are some screen shots:
This line looks incorrect:
notifyItemRangeChanged(typingIndicatorAdapterPosition, itemCount - 1)
Assuming you're trying to change all the items from the typing indicator position through the end of the list, it looks like you're trying to use it as (start, end), but the parameters are actually (start, itemCount), with itemCount being the number of items changed at that index. See the documentation here for more information.

Android recycler view position occurs index error

I tried to control recycler view item visibility when i click button but it does not work
I'm using databinding in xml
this is error message
java.lang.IndexOutOfBoundsException: Index: 5, Size: 4
In my code, recycler view item has a constraintLayout and button
And constraintLayout has recycler view
I want to show constraintLayout of item that has clicked button and hide other item's constraintLayout
The way that i tried to resolve this problem is to use previous position
When button is clicked, hide previous position's item and show current position's item
the code below is what i tried
this is clickListener in activity code
answerAdapter.onItemClickListener = object : QnaDetailAdapter.OnItemClickListener {
override fun onClick(
view: View,
position: Int,
holder: QnaDetailAdapter.AnswerHolder
) {
if (prePosition != -1)
binding.recyclerViewAnswer[prePosition].comment_holder.visibility = View.GONE
if (binding.recyclerViewAnswer[position].comment_holder.visibility == View.GONE) {
binding.recyclerViewAnswer[position].comment_holder.visibility = View.VISIBLE
prePosition = position
} else {
binding.recyclerViewAnswer[position-1].comment_holder.visibility = View.GONE
prePosition = -1
}
}
}
And this is adapter's onBindViewHodler
override fun onBindViewHolder(holder: AnswerHolder, position: Int) {
if (onItemClickListener != null) {
holder.btnComment.setOnClickListener { v ->
onItemClickListener?.onClick(v, position, holder)
}
}
holder.layout.recycler_view_comment.layoutManager = LinearLayoutManager(context)
holder.layout.recycler_view_comment.setHasFixedSize(true)
holder.layout.recycler_view_comment.adapter = adapter
val item = answerList[position]
holder.bind(item)
}
And this is AnswerHodler class
class AnswerHolder(private val binding: QnaDetailItemBinding) :
RecyclerView.ViewHolder(binding.root) {
val btnComment: Button = binding.btnComment
val layout: ConstraintLayout = binding.commentHolder
fun bind(item: Answer) {
binding.item = item
}
}
binding.comment is constraintLayout i touched on
thank for your help
Rather thaan usingposition, use holder.getAdapterPosition()

Change CardBackgroundColor on RecyclerView

I have the following code on my RecyclerView:
class TaskViewHolder(v: View) : RecyclerView.ViewHolder(v), View.OnClickListener
{
var mId: TextView = v.task_id
var mDescription: TextView = v.task_description
var mCard: CardView = v.task_card
var mView: View = v
}
override fun onBindViewHolder(holder: TaskViewHolder, position: Int)
{
// Initialize ViewHolder content
holder.mId.text = items[position].getID().toString()
holder.mDescription.text = items[position].getDescription()
holder.mTask = items[position]
for (elem in priorities)
{
if (elem.getID() == items[position].getPriority())
{
holder.mCard.setCardBackgroundColor(Color.parseColor("#c2c2c2"))
break
}
}
}
I don't know why, but CardView backgroundColor isn't changing.
If I use the following code, it works correctly:
holder.mCard.setCardBackgroundColor(ContextCompat.getColor(holder.mView.context, R.color.priority3))
What I should do to set CardBackgroundColor progrmatically?
First of all, You need to provide else part as transparent or another color to avoid color duplicate render issue. second, you have to pass context from your activity or fragment to adapter and that context will be used to get color like below.
if (elem.getID() == items[position].getPriority())
{
holder.mCard.setCardBackgroundColor(ContextCompat.getColor(mContext, [first color]))
} else {
holder.mCard.setCardBackgroundColor(ContextCompat.getColor(mContext,[second color]))
}
Try replacing "#c2c2c2" with "#ffc2c2c2" to make sure you provide a correct alpha for the background colour. On android, this extra byte added at the beginning represents the alpha of the colour:
#ffc2c2c2
ff: alpha
c2: red
c2: green
c2: blue

Categories

Resources