问题描述
我像这样填充 RecyclerView:
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
只是一个 TextView
。
现在我想让当前播放的歌曲粗体:
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)
当我将此代码放入 OnClickListener
以获取某些 Button
时,它起作用了。项目变粗。但是,我希望在将视图呈现给用户之前发生这种情况。但是当我把这段代码放在 onStart
、onResume
甚至 onViewCreated
中时,两者都
songs?.findViewHolderForAdapterPosition(0)
和
songs?.layoutManager?.findViewByPosition(0)
返回null
。 总是。因此,在我看来,RecyclerView 尚未填充来自 files
的项目。所以问题是,这到底是在 Fragment 生命周期中的什么时候发生的?在什么时候调用上述方法是安全的?
解决方法
现在我想让当前播放的歌曲加粗:
第 1 步:让模型数据反映歌曲是否是当前歌曲。换句话说,无论 files
是什么,都应该保存这些数据。
第 2 步:让您的 onBindViewHolder()
在更新行的视图时考虑到这一点。对于每个 onBindViewHolder()
调用,根据模型数据将 TextView
更新为正常或粗体。
第 3 步:当当前播放的歌曲发生变化时,更新模型数据以反映变化,并在 notifyItemChanged()
上调用 RecyclerView.Adapter
告诉适配器两个位置(以前的当前位置)和新当前)需要重新渲染。
现在我想让当前播放的歌曲加粗:
这不是一个好的解决方案。除了您目前看到的问题之外,它也不适用于滚动:
-
行被回收,所以现在当用户滚动你的列表时,一些随机的其他歌曲是粗体
-
同一行不会在同一位置重复使用,因此当您的用户向后滚动时,您当前播放的歌曲可能不再是粗体
那么问题是,在 Fragment 生命周期中,什么时候会发生这种情况?
片段生命周期与 RecyclerView
何时设置其视图之间没有关系。