C'est vraiment bizarre.
Lorsque j'utilise l'ArrayAdapter standard pour un appel ListView, setItemChecked fonctionne correctement
Mais lorsque vous utilisez un ArrayAdapter personnalisé, ce n'est pas le cas.
Quelle serait la raison? Est-ce un bug? Ou est-ce que je manque quelque chose?
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;
}
}
Votre disposition des lignes doit être Checkable
pour que setItemChecked()
fonctionne, auquel cas Android gérera l'appel de setChecked()
sur votre Checkable
lorsque l'utilisateur clique sur la ligne. Vous n’auriez pas besoin de configurer votre propre OnCheckedChangeListener
.
Pour plus, voir:
Vous devez bien sûr définir le mode de choix pour votre ListView, par exemple:
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Mais si vous utilisez également une présentation personnalisée pour votre élément de liste (R.layout.drawing_list_item
), vous devez vous assurer que votre présentation implémente l'interface Checkable:
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private boolean isChecked = false;
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
changeColor(isChecked);
}
public void toggle() {
this.isChecked = !this.isChecked;
changeColor(this.isChecked);
}
private void changeColor(boolean isChecked){
if (isChecked) {
setBackgroundColor(getResources().getColor(Android.R.color.holo_blue_light));
} else {
setBackgroundColor(getResources().getColor(Android.R.color.transparent));
}
}
}
Ensuite, votre mise en page vérifiable sera définie comme dans l'exemple suivant:
<?xml version="1.0" encoding="utf-8"?>
<it.moondroid.banking.CheckableRelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/drawer_item_layout"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:padding="10dp" >
<ImageView
Android:id="@+id/agenzie_item_icon"
Android:layout_width="30dp"
Android:layout_height="30dp"
Android:layout_alignParentLeft="true"
Android:layout_centerVertical="true"
Android:background="@Android:color/darker_gray"
Android:focusable="false" />
<TextView
Android:id="@+id/agenzie_item_name"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerVertical="true"
Android:layout_toRightOf="@+id/agenzie_item_icon"
Android:focusable="false"
Android:paddingLeft="10dp"
Android:text="item"
Android:textAppearance="?android:attr/textAppearanceSmall"
Android:textColor="#FFFFFF" />
</it.moondroid.banking.CheckableRelativeLayout>
Checkable est une courbe d'apprentissage que je préfère ne pas suivre maintenant. Vous pouvez définir et désélectionner manuellement la CheckBox dans le champ OnItemClickListener
des activités. Conservez une variable transitoire booléenne isChecked
dans la liste MyObject
du ArrayAdapter<MyObject>
.
public void onItemClick(AdapterView<?> av, View v, int position, long arg3) {
final ListView listView = (ListView) findViewById(Android.R.id.list);
MyObject item = (MyObject) listView.getItemAtPosition(position);
item.isChecked = !item.isChecked;
if(item.isChecked)
addItem(item);
else
removeItem(item);
}
Pour rendre compte des utilisateurs qui cliquent sur le CheckBox
lui-même; utilisez la même logique addItem (item)/removeItem (item) dans l'implémentation getView
de votre adaptateur de tableau personnalisé, dans CheckBox
's OnClickListener
.
public View getView(int position, View convertView, ViewGroup viewGroup) {
CheckBox cb = null;
if (convertView == null) {
if(inflater == null) //cache to avoid reconstructing for each view
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView =inflater.inflate(R.layout.list_item_text_right_checkmark, null);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.check);
cb.setChecked((list.get(position).isChecked));
cb.setTag(list.get(position);
public void onClick(View v) {
if(v instanceof CheckBox) {
CheckBox cb = (CheckBox) v;
if(cb.isChecked()) //verify boolean logic here!!!
activityRef.get().addItem(cb.getTag()); //WeakReference to activity
else
activityRef.get().removeItem(cb.getTag());
}
});
} else cb = (CheckBox) convertView.findViewById(R.id.check);
cb.setChecked((list.get(position).isChecked));
...
}
L'appel de CheckBox :: setChecked () est la clé ici.
Cela semble faire l'affaire tant que votre adaptateur RAID peut assumer la même activité et qu'il peut assumer la même définition XML d'élément de liste dans res/layout /.
élément de liste vérifiable XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical" >
<TextView
Android:id="@+id/text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_toLeftOf="@+id/check"
Android:gravity="center_vertical"
Android:paddingLeft="8dp"
Android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
Android:id="@+id/check"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
Android:focusable="false"/>
</RelativeLayout>
Si vous devez vérifier initialement certaines de vos cases à cocher, définissez simplement vos membres isChecked dans votre MyObject avant de gonfler.
Aucune des réponses n'a fonctionné pour moi. Mon problème était que seul l'appel initial à ExpandableListView.setItemChecked à partir de OnCreate/OnStart/OnPause ne fonctionnait pas comme si la vue n'était pas encore complètement initialisée. Afin de résoudre ce problème, je devais faire ce qui suit:
_expandableListView.Post(() =>
{
_expandableListView.SetItemChecked(fragmentPosition, true);
});