В чем разница между состояниями, выбранными, проверенными и активированными в Android?
Я хотел бы знать, чем отличаются эти состояния. Я не нашел никакой веб-страницы, разъясняющей это.
3 ответа:
разница между проверено и активировано на самом деле довольно интересно. Даже документация Google извиняется (акцент ниже добавлен):
... Например, в виде списка с одним или несколькими выделениями включено, виды в текущем наборе выбора активируются. (Um, да, мы глубоко сожалеем о терминологии здесь.) активированный состояние передается детям, считает он находится на.
так вот в чем разница:
- активированный был введен в Honeycomb, поэтому вы не можете использовать его до этого
- активировано теперь свойство каждого представления. Он имеет методы setActivated () и isActivated ()
- активированный распространяется на дочерние элементы представления, на котором он установлен
- Checked вращается вокруг представления, реализующего проверяемый интерфейс. Методы вызове setchecked(), этот флажок установлен(), toggle ()
ListView (после Honeycomb) вызывает setChecked () или setActivated () в зависимости от версии Android, как показано ниже (взято из исходного кода Android):
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) { if (child instanceof Checkable) { ((Checkable) child).setChecked(mCheckStates.get(position)); } else if (getContext().getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { child.setActivated(mCheckStates.get(position)); } }
обратите внимание на переменную mCheckStates. Он отслеживает, какие позиции в вашем списке проверяются / активируются. Они доступны через, например, getCheckedItemPositions(). Обратите внимание также, что вызов ListView.setItemChecked() вызывает выше. Другими словами, его можно было бы с тем же успехом назвать setItemActivated ().
до Honeycomb мы должны были реализовать обходные пути, чтобы отразить state_checked в наших элементах списка. Это связано с тем, что ListView вызывает setChecked() только на самом верхнем представлении в макете (а макеты не реализуют checkable) ... и она не размножается без посторонней помощи. Эти обходные пути имели следующую форму: расширение корневого макета для реализации Checkable. В своем конструкторе рекурсивно найдите все дочерние элементы, которые реализуют Checkable. Когда setChecked () и др... вызываются, передают вызов на эти представления. Если эти представления реализуют список состояний drawables (например, флажок) с другим drawable для state_checked, то проверенное состояние отражается в пользовательском интерфейсе.
чтобы сделать хороший фон для элемента списка после Honeycomb все, что вам нужно сделать, это иметь список состояний drawable с drawable для состояния state_activated, как это (и использовать setItemChecked() конечно):
<item android:state_pressed="true" android:drawable="@drawable/list_item_bg_pressed"/> <item android:state_activated="true" android:drawable="@drawable/list_item_bg_activated"/> <item android:drawable="@drawable/list_item_bg_normal"/>
чтобы сделать хороший фон для элемента списка до HoneyComb, вы бы сделали что-то вроде выше для state_checked, а также вам нужно расширить свой самый верхний вид для реализации проверяемого интерфейса. В этом случае вам нужно сообщить Android, является ли состояние, которое вы реализуете, истинным или ложным, реализуя onCreateDrawableState () и вызывая refreshDrawableState () всякий раз, когда состояние изменения.
<item android:state_pressed="true" android:drawable="@drawable/list_item_bg_pressed"/> <item android:state_checked="true" android:drawable="@drawable/list_item_bg_checked"/> <item android:drawable="@drawable/list_item_bg_normal"/>
... и код для реализации Checkable в сочетании с state_checked в RelativeLayout может быть:
public class RelativeLayoutCheckable extends RelativeLayout implements Checkable { public RelativeLayoutCheckable(Context context, AttributeSet attrs) { super(context, attrs); } public RelativeLayoutCheckable(Context context) { super(context); } private boolean mChecked = false; @Override protected void onFinishInflate() { super.onFinishInflate(); } @Override public boolean isChecked() { return mChecked; } @Override public void setChecked(boolean checked) { mChecked = checked; refreshDrawableState(); } private static final int[] mCheckedStateSet = { android.R.attr.state_checked, }; @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, mCheckedStateSet); } return drawableState; } @Override public void toggle() { setChecked(!mChecked); } }
благодаря следующим:
http://sriramramani.wordpress.com/2012/11/17/custom-states/
Stackoverflow:как добавить пользовательское состояние кнопки
Stackoverflow:пользовательский проверяемый вид, который отвечает к селектору
http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/
по словам doc:
android: state_selected Boolean. "
true
" Если этот элемент должен использоваться, когда объект текущий выбор пользователя при навигации с управлением по направлению (например, при навигации по списку С d-pad);"false
" если этот элемент должен использоваться, когда объект не выбрать. Выбранное состояние используется при фокусировке (android: state_focused) недостаточно (например когда представление списка имеет фокус и элемент внутри него выбирается с помощью d-pad).android: state_checked Boolean. "
true
" Если этот элемент должен использоваться при проверке объекта; "false
" если он должен использоваться, когда объект не проверяется.android: state_activated Boolean. "
true
" Если этот элемент должен использоваться, когда объект включается в качестве постоянного выбор ( как "выделить" ранее выбранный элемент списка в постоянном вид навигации);"false
" если он должен использоваться, когда объект не является активированный. Введено в уровень API 11.Я думаю, что док довольно ясно, так в чем проблема ?
вот другое решение этой проблемы: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java
Я переопределил метод setOnItemClickListener и проверяю разные случаи в коде. Но окончательно решение Марвина гораздо лучше.
listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { CheckedTextView checkedTextView = (CheckedTextView)view.findViewById(R.id.checkedTextView); // Save the actual selected row data boolean checked = checkedTextView.isChecked(); int choiceMode = listView.getChoiceMode(); switch (choiceMode) { // Not choosing anything case (ListView.CHOICE_MODE_NONE): // Clear all selected data clearSelection(); //printCheckedElements(); break; // Single choice case (ListView.CHOICE_MODE_SINGLE): // Clear all the selected data // Revert the actual row data clearSelection(); toggle(checked, checkedTextView, position); //printCheckedElements(); break; // Multiple choice case (ListView.CHOICE_MODE_MULTIPLE): case (ListView.CHOICE_MODE_MULTIPLE_MODAL): // Revert the actual selected row data toggle(checked, checkedTextView, position); //printCheckedElements(); break; } } });