ListView已填充但修改背景色时触发NullPointerException问题排查
ListView空指针问题排查与解决
核心问题原因
ListView.getChildAt(int index)的参数是屏幕上可见子View的相对索引(从0开始,对应第一个出现在屏幕上的子View),但getLastVisiblePosition()返回的是数据源里的绝对位置索引。
你这里两个Item都可见时,getLastVisiblePosition()返回1(对应数据源第二个Item),但如果直接把这个值传给getChildAt,要么因为索引超出可见子View的数量范围返回null,要么就是调用时机太早——ListView还没完成布局、子View还没渲染出来,自然拿不到View对象,触发空指针。
可行解决办法
1. 转换索引匹配可见子View
把数据源的绝对位置转换成可见子View的相对索引,再获取View:
int lastDataPos = listView.getLastVisiblePosition(); // 相对索引 = 绝对位置 - 第一个可见Item的绝对位置 int relativeIndex = lastDataPos - listView.getFirstVisiblePosition(); View targetView = listView.getChildAt(relativeIndex); if (targetView != null) { targetView.setBackgroundColor(Color.GREEN); }
2. 等ListView布局完成再调用
如果是调用时机太早导致的,把代码放到布局完成的监听里:
listView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 移除监听防止重复执行 listView.getViewTreeObserver().removeOnGlobalLayoutListener(this); int lastDataPos = listView.getLastVisiblePosition(); int relativeIndex = lastDataPos - listView.getFirstVisiblePosition(); View targetView = listView.getChildAt(relativeIndex); if (targetView != null) { targetView.setBackgroundColor(Color.GREEN); } } });
3. 自定义Adapter控制样式(更可靠)
如果需要持久化这个样式,避免ListView复用导致样式乱掉,直接在Adapter的getView里处理:
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, names) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); // 给最后一个可见的Item设置背景 if (position == listView.getLastVisiblePosition()) { view.setBackgroundColor(Color.GREEN); } else { // 重置背景,解决View复用的样式残留问题 view.setBackgroundColor(Color.TRANSPARENT); } return view; } }; listView.setAdapter(adapter);
内容的提问来源于stack exchange,提问作者Coderer
相关产品推荐
相关产品推荐

