Яка різниця між станами, вибраними, перевіреними та активованими в Android?


114

Я хотів би знати, чим відрізняються ці стани. Я не знайшов жодної веб-сторінки, яка б це пояснила.


4
Стани перегляду (наприклад, елемент ListView) developer.android.com/guide/topics/resources/…
Луї,

stackoverflow.com/questions/13634259/… - це подібне питання, яке допомогло мені краще зрозуміти це. Перевірте це, чи хочете дізнатися більше.
Acsor

Відповіді:


182

Різниця між перевіреним та активованим насправді досить цікава. Навіть документація Google вибачається (акцент нижче додано):

... Наприклад, у поданні списку з увімкненим одним чи кількома виділеннями активізуються представлення даних у поточному наборі вибору. (Гм, так, нам дуже шкода термінології тут.) Активований стан передається дітям того виду, на який він встановлений.

Тож ось різниця:

  1. Активоване було введено в соти, тому ви не можете його використовувати раніше
  2. Активоване тепер є власністю кожного перегляду. Він має методи setActivate () та isActivate ()
  3. Активоване поширюється дітьми Погляду, на який він встановлений
  4. Перевірено обертається навколо Погляду, що реалізує інтерфейс Checkable. Методи setChecked (), isChecked (), toggle ()
  5. ListView (після Honeycomb) викликає setChecked () OR setActivate () залежно від версії 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 () викликає вищезазначене. Іншими словами, це однаково можна назвати setItemActivate ().

  6. До створення стільникових мереж нам довелося здійснити обхідні шляхи, щоб відобразити стан_контролю в нашому списку. Це тому, що ListView викликає setChecked () ТОЛЬКО на самому верхньому перегляді у макеті (а макети не реалізують перевірку) ... і він НЕ розповсюджується без сторонньої допомоги. Ці способи вирішення набули такої форми: Розширення кореневого макета для реалізації Checkable. У його конструкторі рекурсивно знайдіть усіх дітей, які реалізують Checkable. Коли викликається setChecked () тощо ..., передайте виклик цим переглядам. Якщо ці представлення реалізують чернетки списку станів (наприклад, CheckBox) з іншим малюнком для state_kljuно, то перевірений стан відображається в інтерфейсі користувача.

  7. Щоб зробити гарний фон для елемента списку після Honeycomb, все, що вам потрібно зробити, - це список списку статей, який можна малювати для такого стану state_activate (і, звичайно, використовувати 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, ви зробите щось подібне до вищевказаного для стану_контролю, і вам ТАКОЖ потрібно розширити перегляд у верхній частині, щоб реалізувати інтерфейс Checkable. Після цього вам потрібно повідомити Android, чи стан, який ви реалізуєте, істинне чи помилкове, ввімкнувши OnCreateDravableState () та викликаючи refreshDravableState (), коли стан змінюється.

    <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_ перевіреним у 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: спеціальний вид, який можна перевірити, що відповідає Selector

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

http://developer.android.com/guide/topics/resources/dravable-resource.html#StateList

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


4
ця відповідь безцінна. Я хотів би прочитати його, перш ніж спробувати розробити, як реалізувати макет Checkable, і т. Д. Дякую.
Блейк Мамфорд

12
чудова відповідь, але не стосується "вибраних" пунктів. Я знайшов відповідь у реченнях Selection is a transient property, representing the view (hierarchy) the user is currently interacting with. Activation is a longer-term state that the user can move views in and out of. For example, in a list view with single or multiple selection enabled, the views in the current selection set are activated. (Um, yeah, we are deeply sorry about the terminology here.)
ПРИ ВІД

мій спеціальний колір фону відображається лише за вибраними / сфокусованими елементами, а не за перевіреними елементами, коли використовується метод пост-стільники, який ви опублікували вище: дзвінки setItemChecked()та використання селектора з властивістюandroid:state_activated="true"
woojoo666

1
Дякую вам велике, я витратив три дні, намагаючись розібратися в цьому, поки нарешті не вирішив запитати себе "в чому різниця між перевіреним, вибраним та активованим", відмовляє, що розібратися з чимось таким простим, як меню має бути таким складним, перенапруженим з боку геніїв Google, майже не здається перешкодою, яка була націлена цією компанією для уповільнення інших.
Губатрон

20

Відповідно до док .

  • 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" якщо його слід використовувати, коли об'єкт не активований. Введено в рівень 11 API .

Я думаю, що документ досить зрозумілий, тож у чому проблема?


5
Чи можете ви детальніше зупинитися на android: state_selected. Які обставини, коли це встановлено на істину?
Андерсон

@Anderson це залежатиме від ViewGroup, який ви використовуєте - ListView, RecyclerView (можливо, його LayoutManagers), GridView може мати різні реалізації: ListView виклики setFocused, де виклики GridView setSelected, наприклад. Це може бути випадок перевірки вашого додатка на різних версіях платформи.
ataulm

1
@Anderson: Якщо у вас є список, а у користувача є клавіші зі стрілками, одна клавіша "вибрана", а коли вони стрілки вгору / вниз, вибір переміщується вгору / вниз. Коли вони натискають клавішу "активувати", вона "активує" елемент управління, вважають це виділенням як нечітко схожим на перемикання миші, і перевіряють / активують як нечітко схоже на клацання.
Mooing Duck

Мені було цікаво, я буду використовувати активований для виділення одного елемента в перегляді списку, але чи встановлює він активацію для інших елементів списку на хибну ... якщо не робити жодного з них, це не потрібно знайти інший активований дочірній елемент і встановив активацію на помилкову?
Lion789

0

Ось інше рішення цієї проблеми: 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;
    }
    }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.