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

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

3 ответов


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

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

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

  1. активированный был введен в Honeycomb, поэтому вы не можете использовать его до этого
  2. активировано теперь свойство каждого представления. Он имеет методы setActivated () и isActivated ()
  3. активированный распространяется на дочерние элементы представления, на котором он установлен
  4. Checked вращается вокруг представления, реализующего проверяемый интерфейс. Методы setChecked (), isChecked(), toggle ()
  5. 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 ().

  6. до Honeycomb нам пришлось реализовать обходные пути, чтобы отразить state_checked в наших элементах списка. Это связано с тем, что ListView вызывает setChecked() только на самом верхнем представлении в макете (а макеты не реализуют checkable) ... и она не распространяется без посторонней помощи. Эти обходные пути имели следующую форму: расширьте корневой макет для реализации Checkable. В своем конструкторе рекурсивно найдите все дочерние элементы, реализующие Checkable. Когда вызове setchecked() и т. д... вызываются, передают вызов этим представлениям. Если эти представления реализуют список состояний drawables (например, флажок) с другим drawable для state_checked, то проверенное состояние отражается в пользовательском интерфейсе.

  7. чтобы сделать хороший фон для элемента списка после 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"/>
    

  8. чтобы сделать хороший фон для элемента списка до 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 и проверил случаи differente в коде. Но окончательно решение Марвина гораздо лучше.

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;
    }
    }
});