Android'de seçilen, kontrol edilen ve etkinleştirilen durumlar arasındaki fark nedir?


114

Bu durumları neyin farklılaştırdığını bilmek istiyorum. Bunu açıklayan herhangi bir web sayfası bulamadım.


4
Bir görünümün durumları (örneğin bir ListView öğesi) developer.android.com/guide/topics/resources/…
Louis

stackoverflow.com/questions/13634259/… , bunu daha iyi anlamama yardımcı olan benzer bir soru. Daha fazlasını öğrenmek istiyorsanız kontrol edin.
Acsor

Yanıtlar:


182

Kontrol Edildi ve Etkinleştirildi arasındaki fark aslında oldukça ilginç. Google belgeleri bile özür diler (aşağıda vurgu eklenmiştir):

... Örneğin, tekli veya çoklu seçimin etkinleştirildiği bir liste görünümünde, geçerli seçim kümesindeki görünümler etkinleştirilir. (Um, evet, buradaki terminoloji için çok üzgünüz.) Etkinleştirilmiş durum, üzerine kurulduğu görüşün çocuklarına doğru yayılır.

İşte fark şu:

  1. Activated, Honeycomb'da tanıtıldı, böylece ondan önce kullanamazsınız
  2. Etkinleştirilmiş artık her Görünümün bir özelliğidir. SetActivated () ve isActivated () yöntemlerine sahiptir.
  3. Etkinleştirilmiş, ayarlandığı Görünümün alt öğelerine yayılır
  4. İşaretli, Kontrol Edilebilir arayüzünü uygulayan bir Görünüm etrafında döner. Yöntemler setChecked (), isChecked (), toggle ()
  5. ListView (Honeycomb'dan sonra) aşağıdaki gibi Android sürümüne bağlı olarak setChecked () OR setActivated () öğesini çağırır (Android kaynak kodundan alınmıştır):

    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 değişkenine dikkat edin. Listenizdeki hangi pozisyonların kontrol edildiğini / etkinleştirildiğini takip eder. Bunlara örneğin getCheckedItemPositions () aracılığıyla erişilebilir. ListView.setItemChecked () öğesine yapılan bir çağrının yukarıdakileri çağırdığını da unutmayın. Başka bir deyişle, aynı şekilde setItemActivated () olarak adlandırılabilir.

  6. Honeycomb'dan önce, liste öğelerimizde state_checked'i yansıtmak için geçici çözümler uygulamamız gerekiyordu. Bunun nedeni, ListView'ün YALNIZCA düzendeki en üstteki View'da setChecked () öğesini çağırmasıdır (ve düzenler denetlenebilir değildir) ... ve yardım almadan yayılmaz. Bu geçici çözümler aşağıdaki biçimdeydi: Checkable'ı uygulamak için kök düzenini genişletin. Yapıcısında, Checkable uygulayan tüm alt öğeleri yinelemeli olarak bulun. SetChecked () vb ... çağrıldığında, çağrıyı bu Görünümlere aktarın. Bu görünümler, durum denetimli için farklı bir çekilebilir durum listesi çizimleri (örneğin bir CheckBox) uygularsa, denetlenen durum kullanıcı arayüzüne yansıtılır.

  7. Honeycomb'dan sonra bir liste öğesine güzel bir arka plan oluşturmak için tek yapmanız gereken, state_activated durumu için bir çekilebilir durum listesine sahip olmaktır (ve elbette setItemChecked () kullanın):

    <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'dan önce bir liste öğesine güzel bir arka plan oluşturmak için, state_checked için yukarıdaki gibi bir şey yaparsınız ve ayrıca Kontrol Edilebilir arayüzü uygulamak için en üstteki görünümünüzü genişletmeniz gerekir. Bunun içinde daha sonra, uyguladığınız durumun doğru mu yanlış mı olduğunu, onCreateDrawableState () uygulayarak ve durum her değiştiğinde yenilemeDrawableState () çağırarak Android'e söylemeniz gerekir.

    <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"/>

... ve bir RelativeLayout'ta State_checked ile birlikte Checkable'ı uygulayacak kod şunlar olabilir:

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

Aşağıdakiler sayesinde:

http://sriramramani.wordpress.com/2012/11/17/custom-states/

StackOverflow'daki: Özel bir düğme durumu nasıl eklenir?

StackOverflow'daki: Seçiciye yanıt veren Özel Kontrol Edilebilir Görünüm

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/


4
bu cevap paha biçilemez. Keşke Kontrol Edilebilir bir düzen, vb. Nasıl uygulanacağını bulmaya çalışmadan önce okumanızı isterdim. Çok teşekkür ederim.
Blake Mumford

12
harika yanıt, ancak "seçilen" öğelere hitap etmiyor. Cevabı, alıntıladığınızdan hemen ÖNCE cümlelerde buldum: 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.) kaynak
woojoo666

benim özel arka plan rengim, yukarıda gönderdiğiniz Honeycomb sonrası yöntemini kullanırken işaretli öğelerin değil, yalnızca seçilen / odaklanan öğelerin arkasında görünüyor: arama setItemChecked()ve sonra özellikli bir seçici kullanmaandroid:state_activated="true"
woojoo666

1
Çok teşekkür ederim, sonunda kendime "kontrol edilen, seçilen ve etkinleştirilen arasındaki fark nedir" diye sormaya karar verene kadar bunu anlamaya çalışmakla 3 günümü boşa harcadım, bir menü kadar basit bir şeyle uğraşmanın bu kadar karmaşık, aşırı mühendislik olması gerektiği berbat. Google'ın dahileri tarafından, neredeyse bu şirketin başkalarını yavaşlatmak için bilerek koyduğu bir engel gibi görünüyor.
Gubatron

20

Göre doc :

  • android: state_selected Boolean . " true" Nesne (örneğin bir d-pad ile bir liste gezinirken gibi) yönlendirilmiş bir kumanda ile seyreden geçerli kullanıcı seçimi olduğunda bu madde kullanılmalıdır, eğer; falseBu öğe, nesne seçilmediğinde kullanılacaksa " ". Seçili durum, odak (android: state_focused) yeterli olmadığında kullanılır (örneğin, liste görünümünde odak olduğunda ve içindeki bir öğe d-pad ile seçildiğinde).

  • android: state_checked Boolean . trueBu öğe nesne kontrol edildiğinde kullanılacaksa " "; falseNesne kontrol edilmediğinde kullanılması gerekiyorsa " ".

  • android: state_activated Boolean . trueNesne kalıcı seçim olarak etkinleştirildiğinde bu öğenin kullanılması gerekiyorsa " " (örneğin, kalıcı bir gezinme görünümünde önceden seçilen liste öğesini "vurgulamak"); " false" nesne etkinleştirilmediğinde kullanılması gerekiyorsa. Sunulan API düzeyinde 11 .

Doktorun oldukça açık olduğunu düşünüyorum, peki sorun nedir?


5
Android: state_selected ile ilgili ayrıntılara girebilir misiniz? True olarak ayarlandığında koşullar nelerdir?
Anderson

@Anderson, kullandığınız ViewGroup'a bağlı olacaktır - ListView, RecyclerView (muhtemelen LayoutManager'lar), GridView farklı uygulamalara sahip olabilir: ListView, örneğin GridView setSelected'ı çağırdığı setFocused'ı çağırır. Bu, uygulamanızı farklı platform sürümlerinde kontrol etmeniz olabilir.
ataulm

1
@Anderson: Bir listeniz varsa ve kullanıcının ok tuşları varsa, biri "seçilidir" ve yukarı / aşağı okunduğunda seçim yukarı / aşağı hareket eder. "Etkinleştir" tuşuna bastıkları zaman, kontrolü "etkinleştirir", seçimin belirsiz bir şekilde fareyle üzerine gelmeye benzer olduğunu düşünür ve kontrol / etkinleştirme, belirsiz bir şekilde tıklamaya benzer.
Mooing Duck

Merak ediyordum, bir liste görünümünde bir öğeyi vurgulamak için etkinleştirmeyi kullanacağım, ancak diğer liste öğeleri için etkinleştirmeyi yanlış olarak ayarlıyor mu? diğer etkinleştirilmiş alt öğe ve etkinleştirmeyi yanlış olarak ayarladınız mı?
Lion789

0

İşte bu sorun için başka bir çözüm: https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/android/customizedlistview/MainActivity.java

SetOnItemClickListener yöntemini geçersiz kıldım ve koddaki farklı durumları kontrol ettim. Ama kesinlikle Marvin'in çözümü çok daha iyi.

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;
    }
    }
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.