В чем разница между состояниями, выбранными, проверенными и активированными в Android?

Я хотел бы знать, чем отличаются эти состояния. Я не нашел ни одной веб-страницы, разъясняющей это.

3 ответа

Решение

Разница между Checked и Activated на самом деле довольно интересная. Даже документация Google извиняется (выделено ниже):

... Например, в представлении списка с включенным одиночным или множественным выбором, представления в текущем наборе выбора активируются. (Гм, да, мы глубоко сожалеем о терминологии здесь.) Активированное состояние передается дочерним элементам представления, для которого оно установлено.

Так вот в чем разница:

  1. Активированный был введен в Honeycomb, так что вы не можете использовать его до этого
  2. Активировано теперь свойство каждого просмотра. У него есть методы setActivation () и isActivation ()
  3. Активированный распространяется на потомков вида, на котором он установлен
  4. Checked вращается вокруг View, реализующего интерфейс Checkable. Методы setChecked(), isChecked (), toggle ()
  5. ListView (после Honeycomb) вызывает setChecked() ИЛИ setActivation () в зависимости от версии 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() вызывает вышеуказанное. Другими словами, он также может быть вызван setItemActivation ().

  6. До Honeycomb нам приходилось реализовывать обходные пути, чтобы отразить state_checked в наших элементах списка. Это связано с тем, что ListView вызывает setChecked() ТОЛЬКО для самого верхнего View в макете (а макеты не реализуют checkable) ... и он НЕ распространяется без посторонней помощи. Эти обходные пути имели следующую форму: Расширение корневого макета для реализации Checkable. В своем конструкторе рекурсивно найдите все дочерние элементы, которые реализуют Checkable. Когда вызывается setChecked() и т. Д..., передайте вызов этим представлениям. Если в этих представлениях реализовано рисование списка состояний (например, CheckBox) с другим рисованием для state_checked, то проверенное состояние отражается в пользовательском интерфейсе.

  7. Чтобы создать приятный фон для элемента списка после Honeycomb, все, что вам нужно сделать, - это создать список состояний, который можно нарисовать с помощью drawable для состояния state_activation, вот так (и, конечно, использовать 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"/>
    

  8. Чтобы создать приятный фон для элемента списка до HoneyComb, вы должны сделать что-то похожее на описанное выше для state_checked, и вам также необходимо расширить верхний вид для реализации интерфейса Checkable. В этом случае вам необходимо сообщить 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/

Stackru: как добавить пользовательское состояние кнопки

Stackru: пользовательский проверяемый вид, который отвечает на селектор

http://www.charlesharley.com/2012/programming/custom-drawable-states-in-android/

http://developer.android.com/guide/topics/resources/drawable-resource.html

http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

Согласно документу:

  • android: state_selected Булево. "true"если этот элемент должен использоваться, когда объект является текущим выбором пользователя при навигации с помощью средства управления направлением (например, при навигации по списку с помощью d-pad);"false"если этот элемент следует использовать, когда объект не выбран. Выбранное состояние используется, когда фокус (android:state_focused) недостаточен (например, когда представление списка имеет фокус и элемент внутри него выбирается с помощью d-pad),

  • Android: State_checked Булево. "true"если этот элемент должен использоваться при проверке объекта;"false"если он должен использоваться, когда объект не проверен.

  • android: состояние_активировано логическое. "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;
    }
    }
});
Другие вопросы по тегам