为什么 ListView getChildAt 只能工作到某个索引?
Why is ListView getChildAt working only upto certain index?
我有一个 ListView
和 CheckBox
和 TextView
。我正在尝试使用索引查找 CheckBox
。在我当前的测试场景中,我在 ListView
中有 16 个项目。以下代码一直工作到索引 5,然后给出 IllegalStateException
。为什么会这样? 如何获得所有索引的 CheckBox
? 我相信这与 Layout
仅代表可见行有关。但即使我向下滚动,索引 0 也有效,而大于 5 的索引无效。 ListView
是 class 中的私有属性。代码:
public void inform(View v) {
TextView tv;
CheckBox cb;
String s = "";
int nrItems = lv.getCount();
LinearLayout layout = (LinearLayout) lv.getChildAt(6);
Toast.makeText(getApplicationContext(), Integer.toString(layout.getChildCount()), Toast.LENGTH_SHORT).show();
cb = (CheckBox) layout.getChildAt(0);
Toast.makeText(getApplicationContext(), Boolean.toString(cb.isChecked()), Toast.LENGTH_SHORT).show();
}
只有看得见的风景才真实存在。例如,如果向下滚动看到第 6 行到第 10 行,那么 getChildAt(0);
实际上是第 6 行,因为它是实际存在的第一个视图
编辑:
您可能尝试做的是获取所有复选框的 isChecked() 值。问题是屏幕上的复选框永远不会多于可见的。所以 'all checkboxes' 永远不会全是 16。
复选框本身应该只是一些数据的表示。你不应该依赖 isChecked
上的事实来做某事。您应该保留一个单独的布尔值列表或数组来表示复选框是否被选中。这在重复使用我猜你不会做的行时也很有用。
通过您自己的适配器使用 ListView。
示例:
public class SampleAdapter extends BaseAdapter {
List<Item> mData ; // Don't forget to instantiate this
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
public void setIsChecked(boolean isChecked){
for(Item item : mData){
item.isChecked = isChecked;
}
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Some example. Create or inflate view here
if(convertView == null)
convertView = new CheckBox(parent.getContext());
convertView.isChecked(mData.isChecked);
return convertView ;
}
}
已更新
重点是您需要更改数据而不是直接更改视图。为适配器调用 notofyDataSetChanged() 后,所有视图都将自动更改。
我有一个 ListView
和 CheckBox
和 TextView
。我正在尝试使用索引查找 CheckBox
。在我当前的测试场景中,我在 ListView
中有 16 个项目。以下代码一直工作到索引 5,然后给出 IllegalStateException
。为什么会这样? 如何获得所有索引的 CheckBox
? 我相信这与 Layout
仅代表可见行有关。但即使我向下滚动,索引 0 也有效,而大于 5 的索引无效。 ListView
是 class 中的私有属性。代码:
public void inform(View v) {
TextView tv;
CheckBox cb;
String s = "";
int nrItems = lv.getCount();
LinearLayout layout = (LinearLayout) lv.getChildAt(6);
Toast.makeText(getApplicationContext(), Integer.toString(layout.getChildCount()), Toast.LENGTH_SHORT).show();
cb = (CheckBox) layout.getChildAt(0);
Toast.makeText(getApplicationContext(), Boolean.toString(cb.isChecked()), Toast.LENGTH_SHORT).show();
}
只有看得见的风景才真实存在。例如,如果向下滚动看到第 6 行到第 10 行,那么 getChildAt(0);
实际上是第 6 行,因为它是实际存在的第一个视图
编辑:
您可能尝试做的是获取所有复选框的 isChecked() 值。问题是屏幕上的复选框永远不会多于可见的。所以 'all checkboxes' 永远不会全是 16。
复选框本身应该只是一些数据的表示。你不应该依赖 isChecked
上的事实来做某事。您应该保留一个单独的布尔值列表或数组来表示复选框是否被选中。这在重复使用我猜你不会做的行时也很有用。
通过您自己的适配器使用 ListView。 示例:
public class SampleAdapter extends BaseAdapter {
List<Item> mData ; // Don't forget to instantiate this
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
public void setIsChecked(boolean isChecked){
for(Item item : mData){
item.isChecked = isChecked;
}
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Some example. Create or inflate view here
if(convertView == null)
convertView = new CheckBox(parent.getContext());
convertView.isChecked(mData.isChecked);
return convertView ;
}
}
已更新
重点是您需要更改数据而不是直接更改视图。为适配器调用 notofyDataSetChanged() 后,所有视图都将自动更改。