如何在运行时批量修改RecyclerView中所有条目的字体
代码失效原因
RecyclerView本身只是列表容器,不持有所有子item的控件实例,你直接通过rv_work_preview.tv_work_content查找控件时,系统只会返回当前可视区域内第一个匹配该id的item控件,所以只会修改第一个条目的字体。- 每次点击都调用
Typeface.createFromAsset属于重复加载字体资源,不仅会造成性能损耗,还会引发内存泄漏。
可行实现方案
步骤1:改造RecyclerView的Adapter
在Adapter内部声明全局字体变量,提供外部设置入口,设置后触发列表刷新:
class YourPreviewAdapter : RecyclerView.Adapter<YourPreviewAdapter.ViewHolder>() { // 全局字体变量,默认使用系统默认字体 var currentTypeface: Typeface = Typeface.DEFAULT set(value) { field = value // 刷新列表触发所有item重新绑定 notifyDataSetChanged() } inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val tvWorkContent: TextView = itemView.findViewById(R.id.tv_work_content) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { // 每次绑定item时都应用当前全局字体 holder.tvWorkContent.typeface = currentTypeface // 其余原有绑定逻辑保持不变 } // 其余原有Adapter方法保持不变 }
步骤2:提前缓存字体实例,点击按钮更新全局字体
在页面初始化时提前加载好字体资源,避免重复加载:
// 页面成员变量,提前缓存两种字体 private lateinit var aritaBuriTypeface: Typeface private lateinit var cafe24Typeface: Typeface // 列表Adapter实例 private lateinit var previewAdapter: YourPreviewAdapter // 在onViewCreated等初始化方法中完成资源加载、Adapter初始化 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 仅加载一次字体资源 aritaBuriTypeface = Typeface.createFromAsset(requireActivity().assets, "fonts/arita_buri.otf") cafe24Typeface = Typeface.createFromAsset(requireActivity().assets, "fonts/cafe24_surround_air.ttf") // 初始化Adapter并绑定到RecyclerView previewAdapter = YourPreviewAdapter() rv_work_preview.adapter = previewAdapter // 按钮点击逻辑 rbAritaBuri.setOnClickListener { previewAdapter.currentTypeface = aritaBuriTypeface } rbCafe24.setOnClickListener { previewAdapter.currentTypeface = cafe24Typeface } }
性能优化提示
如果觉得notifyDataSetChanged全量刷新性能损耗较大,可以仅刷新当前可见区域的item:
// 可以把字体设置逻辑挪到页面层,避免Adapter持有RecyclerView实例 rbAritaBuri.setOnClickListener { previewAdapter.currentTypeface = aritaBuriTypeface val layoutManager = rv_work_preview.layoutManager as LinearLayoutManager val firstVisible = layoutManager.findFirstVisibleItemPosition() val lastVisible = layoutManager.findLastVisibleItemPosition() previewAdapter.notifyItemRangeChanged(firstVisible, lastVisible - firstVisible + 1) }
内容的提问来源于stack exchange,提问作者sejigner
相关产品推荐
相关产品推荐

