Android Studio getView根据布尔值设条目颜色出现复用错乱问题
问题原因
你遇到的非紧急条目被错误改色的问题是两个典型的Adapter View复用逻辑错误导致的:
- 你代码中判断颜色用的
urgent变量没有绑定当前position对应的待办条目,不是当前渲染条目自身的属性值,判断逻辑从根源上就不对。 - 你只处理了
urgent == true时的样式设置,没有处理urgent == false的分支。ListView的getView会复用滚出屏幕的旧View,当之前渲染紧急条目时被改成红底白字的View被复用来展示非紧急条目时,因为你没有给非紧急条目重置回默认样式,旧View的红底白字样式会被保留,就会出现非紧急条目颜色错误的问题。
你之前的两个尝试无效的原因也很明确:
- 把
findViewById移到if(old == null)之前会崩溃:当old为null时,还没有inflate出条目布局,此时调用findViewById会触发空指针。 - 把颜色判断移入
old == null块内无法解决问题:这个代码块只有新建View的时候才会执行,复用旧View的时候根本不会走颜色设置逻辑,复用的旧View会直接带着之前的样式展示,必然出错。
修复方案
核心要改两个点:一是每次渲染都取当前position对应条目的urgent属性做判断;二是无论条目是否紧急,都要显式设置对应的样式,不能遗漏非紧急状态的样式重置。
修复后的getView代码如下:
@Override public View getView(int position, View old, ViewGroup parent) { View itemView = old; LayoutInflater inflater = getLayoutInflater(); if(itemView == null) { itemView = inflater.inflate(R.layout.todo_items, parent, false); } TextView textView = itemView.findViewById(R.id.textView); // 取当前位置对应的待办条目 Todo currentTodo = getItem(position); textView.setText(currentTodo.toString()); // 必须同时处理紧急、非紧急两种状态 if(currentTodo.isUrgent()) { itemView.setBackgroundColor(Color.RED); textView.setTextColor(Color.WHITE); } else { // 重置为非紧急条目的默认样式,覆盖复用View残留的样式 itemView.setBackgroundColor(Color.WHITE); // 替换为你自己的默认背景色 textView.setTextColor(Color.BLACK); // 替换为你自己的默认文字颜色 } return itemView; }
如果要进一步优化滚动性能,可以加ViewHolder模式缓存控件引用,避免每次调用getView都执行findViewById,但上面的代码已经可以完全解决你现在的颜色错乱问题。
内容的提问来源于stack exchange,提问作者user16064117
相关产品推荐
相关产品推荐

