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


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

3 94

3 ответа:

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

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

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

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

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