Issue
I populate the RecyclerView like this:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.player, container, false)
view.findViewById<RecyclerView>(R.id.songs).adapter = object: RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val item = LayoutInflater.from(parent.context).inflate(R.layout.item_song, parent, false)
return MyViewHolder(item)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
(holder.item as TextView).text = files[position].tag.title()
}
override fun getItemCount(): Int = files.size
}
return view
}
item_song.xml
is just a TextView
.
Now I want to make the currently playing song Bold:
val songs = view?.findViewById<RecyclerView>(R.id.songs)
val song = songs?.findViewHolderForAdapterPosition(0)?.itemView as TextView
// or val song = songs?.layoutManager?.findViewByPosition(0) as TextView
song.setTypeface(song.typeface, Typeface.BOLD)
When I throw this code into the OnClickListener
for some Button
, it works. The item gets bold. However, I want this to happen before the view is presented to the user. But when I put this code in onStart
, onResume
, or even in onViewCreated
, both
songs?.findViewHolderForAdapterPosition(0)
and
songs?.layoutManager?.findViewByPosition(0)
return null
. Always. Thus it seems to me that the RecyclerView has not been populated yet with the items from files
. So the question is, when exactly in the Fragment lifecycle does that happen? At what point is it safe to call above methods?
Solution
Now I want to make the currently playing song Bold:
Step #1: Have the model data reflect whether or not the song is current. In other words, whatever files
is should hold this data.
Step #2: Have your onBindViewHolder()
take this into account when updating the views of the row. For every onBindViewHolder()
call, update the TextView
to be normal or bold based on the model data.
Step #3: When the currently-playing song changes, update the model data to reflect the changes, and call notifyItemChanged()
on the RecyclerView.Adapter
to tell the adapter that the two positions (formerly-current and newly-current) need to be re-rendered.
Now I want to make the currently playing song Bold:
That is not a good solution. Beyond the problems that you are currently seeing, it will not work with scrolling:
Rows get recycled, and so now some random other song is bold as the user scrolls your list
The same row does not get reused for the same position, so when your user scrolls back, your currently-playing song might not be bold anymore
So the question is, when exactly in the Fragment lifecycle does that happen?
There is no relationship between the fragment lifecycle and when the RecyclerView
sets up its views.
Answered By - CommonsWare
Answer Checked By - Cary Denson (JavaFixing Admin)