Reputation: 105
I have created a RecyclerView in which the user can press a "Now" button and it would update recycler view's TextViews with the current date and time.
Weirdly, if I press the "Now" button on the recycler view at position 0, it also updates the RecyclerView at position 9. Similarly, pressing it at position 1 also updates it at position 10.
Currently, the date and time are not saved anywhere; that part hasn't been set up yet. I'm just trying to figure out why clicking the button updates two views 10 positions apart.
Here is the code for my adapter; I'm using Kotlin:
class TimeStampListAdapter(private val labelList: ArrayList<TimeStampLabels>,
private val context: Context) : RecyclerView.Adapter<TimeStampListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder {
val view: View = LayoutInflater.from(context).inflate(R.layout.list_time_category, parent, false)
return ViewHolder(view, context, labelList)
}
override fun getItemCount(): Int {
return labelList.size
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder?.bindItem(labelList[position])
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var tsDate = itemView.findViewById(R.id.txtEDate) as EditText
var tsTime = itemView.findViewById(R.id.txtETime) as EditText
var categoryLabel = itemView.findViewById(R.id.txtVCategory) as TextView
var nowButton = itemView.findViewById(R.id.btnNow) as Button
val calendar = Calendar.getInstance()
// Inserts the time stamp labels into each RecyclerView instance
fun bindItem(label: TimeStampLabels) {
categoryLabel.text = label.tsLabel
nowButton.setOnClickListener(this)
}
override fun onClick(v: View?) {
var dateFormat = SimpleDateFormat("MM / dd / yyyy")
var timeFormat = SimpleDateFormat("HH:mm")
var date = dateFormat.format(calendar.timeInMillis)
var time = timeFormat.format(calendar.getTime())
// Get the position of relevant row
var position: Int = adapterPosition
Log.d("POSITION: ", position.toString())
var mList = labelList[position]
if (v!!.id == nowButton.id) {
Log.d("POSITION in conditional", position.toString())
tsDate.setText(date)
tsTime.setText(time)
//notifyItemChanged(adapterPosition) - This isn't needed,
// but if uncommented doesn't help the main issue I'm
// having.
}
}
The issue occurs on the firing of the overridden onClick function.
The Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_time_stamp)
labelListItems = ArrayList()
adapter = TimeStampListAdapter(labelListItems!!, this )
layoutManager = LinearLayoutManager(this)
timeStampRecyclerView.layoutManager = layoutManager
timeStampRecyclerView.adapter = adapter
/**
* Create the recycler views out of the TimeStampLabels table
*/
for (i in 0..labels.timeStampLabels!!.size - 1) {
val label = TimeStampLabels()
label.tsLabel = label.timeStampLabels[i]
labelListItems!!.add(label)
}
adapter!!.notifyDataSetChanged()
}
Upvotes: 2
Views: 139
Reputation: 1034
That is happening because recycler view as name suggests it recycle(reuses) the view so it can save memory and give user smooth scrolling experience, refer this link for more details https://developer.android.com/guide/topics/ui/layout/recyclerview
So you have create two more fields in your model class TimeStampLabels which will store date and time and then you have to change onClick implementation as below
override fun onClick(v: View?) {
var dateFormat = SimpleDateFormat("MM / dd / yyyy")
var timeFormat = SimpleDateFormat("HH:mm")
var date = dateFormat.format(calendar.timeInMillis)
var time = timeFormat.format(calendar.getTime())
// Get the position of relevant row
var position: Int = adapterPosition
Log.d("POSITION: ", position.toString())
var mList = labelList[position]
// What ever name you give for date and time field in your model class
mList.date = date
mList.time = time
labelList[position] = mList
notifyDataSetChanged()
}
and change your bindItem method like below
fun bindItem(label: TimeStampLabels) {
// What ever name you give for date and time field in your model class
tsDate.setText(label.date)
tsTime.setText(label.time)
categoryLabel.text = label.tsLabel
nowButton.setOnClickListener(this)
}
Upvotes: 1