Android - RecyclerView - edittext notifyItemChanged keep focus and continue typing

2.3k Views Asked by At

I have a RecyclerView which has an EditText in its items.

For each EditText I have added a textChangeListener.

Whenever the user types a character I want to do an input validation and so I can change the item, for example show red border in case of wrong input etc...

After I do the validation I call:

adapter.notifyItemChanged(itemPosition) 

to update the view.

But the problem is that the focus is lost from the EditText and I have to click again inside the box in order to continue typing.

Is there a solution for this case? How can I continue typing while the view is updated after calling notifyItemChanged ?

enter image description here

ADAPTER

class ItemAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
     val inflater = LayoutInflater.from(parent.context)
     val binding = LayoutItemBinding.inflate(inflater, parent, false)
     binding.editText.addTextChangedListener {
        // Do layout changes....
        if (isInvalidInput) {
          item.setError = true
          ....
          ...
        }
        
        adapter.notifyItemChanged(itemPosition)
     }
     return ItemViewHolder(binding)
  }

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

  inner class ItemViewHolder(val binding: LayoutItemBinding) 
  : RecyclerView.ViewHolder(binding.root) {

      fun bind(model: ItemModel) {
            // Setup view for item
        }
  }

}
3

There are 3 best solutions below

1
On

First, Please post your code.

If you called notifyDatasetChanged(), all views of recyclerview will refreshed (it means that the views could be recreated.).

So if you want remain focus in edittext, you not call notifyDatasetChanged() or set focus to your edittext after notifyDataChanged().

But setFocus is bit more difficult. So I suggest method that update views of recyclerview without call notifyDatasetChanged(). I think you can directly update view of recyclerview without call notifyDataChanged().

0
On

Try to move your error setting code in the bind function of the ViewHolder and update the error status outside of the TextWatcher:

class ItemAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() 
{   
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = LayoutItemBinding.inflate(inflater, parent, false)
        
        return ItemViewHolder(binding)
    }

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

    inner class ItemViewHolder(val binding: LayoutItemBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(model: ItemModel, position: Int) {
            binding.editText.addTextChangedListener {
                // Update the ItemModel on text change
                adapter.notifyItemChanged(position)
            }

            // Update the view error status everytime it is updated
            val isInvalidInput = ... // Add your logic
            if (isInvalidInput) {
                model.setError = true
                ....
                ....
            }    
        }
    }
}
0
On

You should save the id of item that contains the EditText that is editing. And in the bind() method of ViewHolder, you will check if the item is currently being edit, you will call requestFocus() method on EditText. And please take note that when you call notifyDataChanged(), the RecycleView maybe check the data of each item to know whether it was changed or not. If the data of an item was changed, RecycleView will redraw that item.