切换Fragment或返回应用后GradientDrawable背景异常缩放问题求助
切换Fragment或返回应用后GradientDrawable背景异常缩放问题求助
我看你遇到了个挺闹心的UI问题——切换Fragment或者把应用切后台再回来时,RecyclerView条目里的GradientDrawable背景就乱掉了对吧?先帮你梳理下可能的原因,再给你几个具体的排查和解决方向:
首先,你的Adapter里有个明显的性能+状态隐患
看你在onBindViewHolder里每次绑定条目时,都给子RecyclerView(timetableList)重新创建LayoutManager、ItemAnimator甚至全新的TimetableAdapter:
binding.timetableList.layoutManager = LinearLayoutManager(context) binding.timetableList.itemAnimator = DefaultItemAnimator() binding.timetableList.adapter = TimetableAdapter(context).apply { showTimetableList(value) }
这种写法会导致RecyclerView的子View被频繁销毁重建,不仅性能拉胯,还会触发Drawable的重复测量与状态重置——这大概率是你背景异常的核心诱因之一。
优化方案:把这些初始化操作移到ViewHolder创建时只做一次,绑定的时候只更新数据:
- 给
StationViewHolder加个初始化块,提前配置好子RecyclerView:
inner class StationViewHolder(val binding: ElementTimetableBinding) : RecyclerView.ViewHolder(binding.root) { private val timetableAdapter = TimetableAdapter(context) init { // 只初始化一次,复用整个生命周期 binding.timetableList.layoutManager = LinearLayoutManager(context) binding.timetableList.itemAnimator = DefaultItemAnimator() binding.timetableList.adapter = timetableAdapter } // 暴露更新数据的方法 fun updateTimetable(data: List<TubeTime>) { timetableAdapter.showTimetableList(data) } }
- 然后在
onBindViewHolder里只调用更新方法:
is Status.Normal -> { with(holder) { val entry = timetable[position] binding.directionText.text = if (entry.key.id.length == 1) "Platform ${entry.key.id}" else entry.key.id // 只更新数据,不重建Adapter updateTimetable(entry.value) } }
其次,GradientDrawable的状态共享问题
你的背景用的是@drawable/transport_card(GradientDrawable),默认情况下,所有引用这个资源的View会共享同一个Drawable实例的状态。当View被Recycler回收复用、或者Fragment重建时,Drawable的边界/缩放状态可能被错误复用,导致显示异常。
解决办法:给每个View的Drawable设置独立状态,在ViewHolder初始化时手动创建Drawable并调用mutate():
inner class StationViewHolder(val binding: ElementTimetableBinding) : RecyclerView.ViewHolder(binding.root) { private val timetableAdapter = TimetableAdapter(context) init { // 给根布局设置独立的背景Drawable val background = ContextCompat.getDrawable(itemView.context, R.drawable.transport_card)?.mutate() itemView.background = background // 同时给子RecyclerView也设置独立的Drawable val listBackground = ContextCompat.getDrawable(itemView.context, R.drawable.transport_card)?.mutate() binding.timetableList.background = listBackground // 其他RecyclerView初始化代码... } // ... }
mutate()方法会让Drawable脱离资源池的共享状态,每个View都拥有自己的Drawable实例,不会互相干扰。
最后,额外排查点
- 检查
TimetableAdapter里有没有修改背景Drawable的代码,如果有,确保每次更新数据时都正确重置了Drawable的边界; - 确认你的Fragment在切换/后台返回时,有没有触发不必要的重建,避免RecyclerView被频繁销毁重建;
- 可以尝试在
StationAdapter的showTimetable方法里,先清空旧的timetable列表再添加新数据,确保数据更新的原子性。
先试试上面的前两个优化,应该能解决大部分问题~
内容来源于stack exchange
相关产品推荐
相关产品推荐

