ListView:setItemChecked 仅适用于标准 ArrayAdapter - 使用自定义 ArrayAdapter 时不起作用?
这实在是太奇怪了。
当我对 ListView 使用标准 ArrayAdapter 时,调用 setItemChecked 可以正常工作,
但是当使用定制的 ArrayAdapter 时,则不行。
原因是什么?这是一个错误吗?或者我错过了什么?
public class Test_Activity extends Activity {
/** Called when the activity is first created. */
private List<Model> list;
private ListView lView;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
setContentView(R.layout.main);
lView = (ListView) findViewById(R.id.ListView01);
lView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list = getModel();
//with this adapter setItemChecked works OK
lView.setAdapter(new ArrayAdapter<Model>(this,
android.R.layout.simple_list_item_multiple_choice, list));
//**************************
//PROBLEM: with this adapter it does not check any items on the screen
// ArrayAdapter<Model> adapter = new Test_Class1(this, list);
// lView.setAdapter(adapter);
}
private List<Model> getModel() {
List<Model> list = new ArrayList<Model>();
list.add(get("0"));
list.add(get("1"));
list.add(get("2"));
list.get(1).setSelected(true);
Model m = list.get(1);
list.add(get("3"));
list.add(get("4"));
list.add(get("5"));
list.add(get("6"));
list.add(get("7"));
// Initially select one of the items
return list;
}
private Model get(String s) {
return new Model(s);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.results_screen_option_menu, menu);
return true;
}
/**
* @category OptionsMenu
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_all: {
int size = lView.getAdapter().getCount();
for (int i = 0; i <= size; i++) {
//************************** PROBLEM
lView.setItemChecked(i, true); // selects the item only for standard ArrayAdapter
Log.i("xxx", "looping " + i);
}
}
return true;
case R.id.select_none:
return true;
}
return false;
}
}
//------------------------------------------------ ------------
public class Test_Class1 extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
public Test_Class1(Activity context, List<Model> list) {
super(context, R.layout.rowbuttonlayout2, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
Log.i("xxx", "-> getView " + position);
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
Log.i("xxx", "-> onCheckedChanged");
element.setSelected(buttonView.isChecked());
Log.i("xxx", "<- onCheckedChanged");
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
Log.i("xxx", "holder.checkbox.setChecked: " + position);
holder.checkbox.setChecked(list.get(position).isSelected());
Log.i("xxx", "<- getView " + position);
return view;
}
}
This is really weird.
When I use the standard ArrayAdapter for a ListView calling setItemChecked works OK
But when using a custom made ArrayAdapter it does not.
What would be the reason? Is this a bug? Or am I missing something?
public class Test_Activity extends Activity {
/** Called when the activity is first created. */
private List<Model> list;
private ListView lView;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
setContentView(R.layout.main);
lView = (ListView) findViewById(R.id.ListView01);
lView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list = getModel();
//with this adapter setItemChecked works OK
lView.setAdapter(new ArrayAdapter<Model>(this,
android.R.layout.simple_list_item_multiple_choice, list));
//**************************
//PROBLEM: with this adapter it does not check any items on the screen
// ArrayAdapter<Model> adapter = new Test_Class1(this, list);
// lView.setAdapter(adapter);
}
private List<Model> getModel() {
List<Model> list = new ArrayList<Model>();
list.add(get("0"));
list.add(get("1"));
list.add(get("2"));
list.get(1).setSelected(true);
Model m = list.get(1);
list.add(get("3"));
list.add(get("4"));
list.add(get("5"));
list.add(get("6"));
list.add(get("7"));
// Initially select one of the items
return list;
}
private Model get(String s) {
return new Model(s);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.results_screen_option_menu, menu);
return true;
}
/**
* @category OptionsMenu
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_all: {
int size = lView.getAdapter().getCount();
for (int i = 0; i <= size; i++) {
//************************** PROBLEM
lView.setItemChecked(i, true); // selects the item only for standard ArrayAdapter
Log.i("xxx", "looping " + i);
}
}
return true;
case R.id.select_none:
return true;
}
return false;
}
}
//------------------------------------------------------------
public class Test_Class1 extends ArrayAdapter<Model> {
private final List<Model> list;
private final Activity context;
public Test_Class1(Activity context, List<Model> list) {
super(context, R.layout.rowbuttonlayout2, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
Log.i("xxx", "-> getView " + position);
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
Log.i("xxx", "-> onCheckedChanged");
element.setSelected(buttonView.isChecked());
Log.i("xxx", "<- onCheckedChanged");
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
Log.i("xxx", "holder.checkbox.setChecked: " + position);
holder.checkbox.setChecked(list.get(position).isSelected());
Log.i("xxx", "<- getView " + position);
return view;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的行布局需要是
Checkable
才能使setItemChecked()
正常工作,在这种情况下,Android 将管理在您的上调用
。您不需要设置自己的setChecked()
当用户单击该行时可检查OnCheckedChangeListener
。有关更多信息,请参阅:
Your row layout needs to be
Checkable
forsetItemChecked()
to work, in which case Android will manage callingsetChecked()
on yourCheckable
as the user clicks on the row. You would not need to be setting up your ownOnCheckedChangeListener
.For more, see:
当然,您必须为 ListView 设置选择模式,例如:
但是如果您还为列表项使用自定义布局 (
R.layout.drawing_list_item
),那么您必须确保您的布局实现了 Checkable 接口:那么您的可检查布局将定义为以下示例:
For sure you have to set the choice mode for your ListView, for example:
But if you're also using a custom layout for your list item (
R.layout.drawing_list_item
), then you have to make sure your layout implements the Checkable interface:Then your checkable layout will be defined as the following example:
Checkable 是一个我现在不想采用的学习曲线。您可以在活动的
OnItemClickListener
中手动设置和取消设置复选框。在ArrayAdapter
的MyObject
列表中维护一个布尔isChecked
瞬态变量。考虑到用户点击
CheckBox
本身;在CheckBox
的OnClickListener
中的自定义数组适配器的getView
实现中使用相同的 addItem(item)/removeItem(item) 逻辑。调用 CheckBox::setChecked() 是这里的关键。
只要您的数组适配器可以承担相同的活动,并且您的数组适配器可以在 res/layout/ 中承担相同的列表项 xml 定义,这似乎就可以解决问题。
可检查列表项 XML:
如果您需要最初检查某些复选框,只需在膨胀之前在 MyObject 中设置 isChecked 成员即可。
Checkable is a learning curve I prefer not to take right now. You can set and unset the CheckBox manually in the Activities'
OnItemClickListener
. Maintain a booleanisChecked
transient variable in theMyObject
list in theArrayAdapter<MyObject>
.To account for users clicking the
CheckBox
itself; use the same addItem(item)/removeItem(item) logic in your custom array adapter'sgetView
implementation, in theCheckBox
'sOnClickListener
.Calling CheckBox::setChecked() is the key here.
This seems to do the trick as long as your array adapter can assume the same activity, and your array adapter can assume the same list item xml definition in res/layout/.
checkable list item XML:
If you need to check some of your CheckBoxs initially, just set your isChecked members in your MyObject prior to inflating.
这些回应都不适合我。我的问题是,只有从 OnCreate/OnStart/OnPause 对 ExpandableListView.setItemChecked 的初始调用不起作用,就好像视图尚未完全初始化一样。为了解决这个问题,我必须执行以下操作:
None of the responses worked for me. My problem was that only the initial call to ExpandableListView.setItemChecked from OnCreate/OnStart/OnPause did not work as if the view was not fully initialized yet. In order to solve this, I had to do the following: