StickyListHeadersAdapter复用同色ColorDrawable背景显示异常问题
问题
我通过se.emilsjolander.stickylistheaders.StickyListHeadersAdapter定义了自定义适配器MyCustomStickyListAdapter,用于展示筛选后的Movies列表。通过自定义方法setViewCompositeBackgroundColor,利用LayerDrawable为列表行设置分段背景色:条件不满足时用默认白色,满足时用绿色、红色、粉色等颜色。
相关实现代码如下:
- 导入包:
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
- 自定义适配器:
public class MyCustomStickyListAdapter extends BaseAdapter implements StickyListHeadersAdapter, Filterable { ... }
- 设置背景色方法:
private void setViewCompositeBackgroundColor(View convertView, ColorDrawable[] colors){ LayerDrawable background = new LayerDrawable(colors); for(int i = 0; i < colors.length; i++) { background.setLayerInsetLeft(i, (i * windowWidth) / colors.length); background.setLayerInsetRight(i, windowWidth - (((i + 1) * windowWidth) / colors.length)); } convertView.setBackground(background); }
- ColorDrawable类变量初始化:
colorDefault = new ColorDrawable(ContextCompat.getColor(context, R.color.colorDefault));
- 颜色定义XML:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="green">@color/Green</color> <color name="red">@color/red</color> <color name="pink">@android:color/pink</color> <color name="default">@color/White</color> </resources>
但遇到问题:当传入包含相同Color ID的ColorDrawable数组(比如两个默认白色)时,左侧同色层会偏移到最右侧同色层的位置,显示效果不符合预期。例如前两个条件为默认白色、第三个为粉色时,实际显示左侧是列表默认灰色,仅右侧显示深色白色和粉色,预期应该是左侧两段白色、右侧一段粉色。
解决方案
原因分析
问题核心是重复使用同一个ColorDrawable实例:LayerDrawable会将相同的Drawable实例视为同一个图层,后续设置的inset参数会覆盖之前的配置,导致前面的同色图层偏移到最后一个同色图层的位置。
修复步骤
- 避免复用ColorDrawable实例
不要直接传递重复的colorDefault实例,每次需要默认色时,新建一个ColorDrawable对象,确保每个图层都是独立实例。
示例修改:
// 错误写法:重复使用同一个实例 // ColorDrawable[] colors = {colorDefault, colorDefault, pinkDrawable}; // 正确写法:每次新建独立实例 ColorDrawable[] colors = { new ColorDrawable(ContextCompat.getColor(context, R.color.colorDefault)), new ColorDrawable(ContextCompat.getColor(context, R.color.colorDefault)), new ColorDrawable(ContextCompat.getColor(context, R.color.pink)) };
- 封装工具方法简化调用
可以封装一个获取独立ColorDrawable的工具方法,减少重复代码:
private ColorDrawable getColorDrawable(int colorResId) { return new ColorDrawable(ContextCompat.getColor(context, colorResId)); } // 调用示例 ColorDrawable[] colors = { getColorDrawable(R.color.colorDefault), getColorDrawable(R.color.colorDefault), getColorDrawable(R.color.pink) };
- 可选:带实例复制的缓存优化
如果担心频繁创建实例的性能问题,可以维护颜色缓存,但返回时必须返回实例副本,避免复用:
private HashMap<Integer, ColorDrawable> colorCache = new HashMap<>(); private ColorDrawable getColorDrawable(int colorResId) { int colorValue = ContextCompat.getColor(context, colorResId); if (!colorCache.containsKey(colorValue)) { colorCache.put(colorValue, new ColorDrawable(colorValue)); } // 返回副本,保证每个图层实例独立 return new ColorDrawable(colorValue); }
修改后,每个图层都是独立的ColorDrawable实例,LayerDrawable会正确应用每个图层的inset设置,实现预期的分段背景效果。
内容的提问来源于stack exchange,提问作者AMPIZBUD
相关产品推荐
相关产品推荐

