อะไรคือความแตกต่างระหว่างสถานะที่เลือกตรวจสอบและเปิดใช้งานใน Android


114

ฉันต้องการทราบว่ารัฐเหล่านั้นแตกต่างกันอย่างไร ฉันไม่พบหน้าเว็บใดที่อธิบายเรื่องนี้


4
สถานะของมุมมอง (เช่นรายการ ListView) developer.android.com/guide/topics/resources/…
Louis

stackoverflow.com/questions/13634259/…เป็นคำถามที่คล้ายกันซึ่งช่วยให้ฉันเข้าใจเรื่องนี้ดีขึ้น ตรวจสอบหากคุณต้องการเรียนรู้เพิ่มเติม
Acsor

คำตอบ:


182

ความแตกต่างระหว่าง Checked และ Activated นั้นค่อนข้างน่าสนใจ แม้แต่เอกสารของ Google ก็ขออภัย (เน้นที่เพิ่มด้านล่าง):

... ตัวอย่างเช่นในมุมมองรายการที่เปิดใช้งานการเลือกเดียวหรือหลายรายการมุมมองในชุดการเลือกปัจจุบันจะเปิดใช้งาน (อืมใช่เราขออภัยเป็นอย่างยิ่งเกี่ยวกับคำศัพท์ที่นี่)สถานะเปิดใช้งานจะแพร่กระจายไปยังเด็ก ๆ ของมุมมองที่ตั้งไว้

นี่คือความแตกต่าง:

  1. เปิดใช้งานแล้วใน Honeycomb ดังนั้นคุณจึงไม่สามารถใช้งานได้ก่อนหน้านั้น
  2. ตอนนี้เปิดใช้งานแล้วเป็นคุณสมบัติของทุก View มันมีเมธอด setActivated () และ isActivated ()
  3. เปิดใช้งานเผยแพร่ไปยังลูกของมุมมองที่ตั้งค่าไว้
  4. การตรวจสอบหมุนรอบมุมมองที่ใช้อินเทอร์เฟซที่ตรวจสอบได้ วิธี 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 ซ้ำ ๆ เมื่อมีการเรียก setChecked () ฯลฯ ... ให้ส่งต่อไปยังมุมมองเหล่านั้น หากมุมมองเหล่านั้นใช้รายการสถานะ drawables (เช่น CheckBox) ที่มี drawable อื่นสำหรับ state_checked สถานะที่ตรวจสอบจะแสดงใน UI

  7. ในการทำพื้นหลังที่ดีให้กับรายการหลังจาก Honeycomb สิ่งที่คุณต้องทำคือมีรายการสถานะที่วาดได้พร้อมกับ drawable สำหรับ state 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 และคุณยังต้องขยายมุมมองที่สูงที่สุดของคุณเพื่อใช้อินเทอร์เฟซ 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/

Stackoverflow: วิธีเพิ่มสถานะปุ่มแบบกำหนดเอง

Stackoverflow: Custom Checkable View ซึ่งตอบสนองต่อ Selector

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
คำตอบนี้ไม่มีค่า ฉันหวังว่าฉันจะอ่านมันก่อนที่จะพยายามหาวิธีใช้เลย์เอาต์ที่ตรวจสอบได้ ฯลฯ ขอบคุณมาก
Blake Mumford

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.) มา
woojoo666

สีพื้นหลังที่กำหนดเองของฉันจะปรากฏหลังรายการที่เลือก / โฟกัสเท่านั้นไม่ใช่รายการที่เลือกเมื่อใช้วิธีการโพสต์รังผึ้งที่คุณโพสต์ไว้ด้านบน: การโทรsetItemChecked()แล้วใช้ตัวเลือกที่มีคุณสมบัติandroid:state_activated="true"
woojoo666

1
ขอบคุณมากฉันเสียเวลา 3 วันในการพยายามคิดออกจนในที่สุดฉันก็ตัดสินใจถามตัวเองว่า "อะไรคือความแตกต่างระหว่างการตรวจสอบเลือกและการเปิดใช้งาน" แย่จังที่จัดการกับบางสิ่งที่เรียบง่ายอย่างที่เมนูจะต้องซับซ้อนและใช้งานมากเกินไป โดยอัจฉริยะของ Google ดูเหมือนว่าเกือบจะเป็นอุปสรรคที่กำหนดโดย บริษัท นี้เพื่อทำให้คนอื่นช้าลง
Gubatron

20

ตามเอกสาร :

  • หุ่นยนต์: state_selected บูลีน " true" หากรายการนี้ควรใช้เมื่อวัตถุเป็นการเลือกผู้ใช้ปัจจุบันเมื่อนำทางด้วยการควบคุมทิศทาง (เช่นเมื่อนำทางผ่านรายการด้วย d-pad) " false" หากควรใช้รายการนี้เมื่อไม่ได้เลือกวัตถุ สถานะที่เลือกจะใช้เมื่อโฟกัส (android: state_focused) ไม่เพียงพอ (เช่นเมื่อมุมมองรายการมีโฟกัสและรายการภายในถูกเลือกด้วย d-pad)

  • หุ่นยนต์: state_checked บูลีน " true" ถ้ารายการนี้ควรใช้เมื่อตรวจสอบวัตถุ " false" หากควรใช้เมื่อยกเลิกการตรวจสอบวัตถุ

  • หุ่นยนต์: state_activated บูลีน " true" หากควรใช้รายการนี้เมื่อเปิดใช้งานออบเจ็กต์เป็นการเลือกแบบต่อเนื่อง (เช่นเพื่อ "ไฮไลต์" รายการที่เลือกไว้ก่อนหน้านี้ในมุมมองการนำทางแบบต่อเนื่อง) " false" หากควรใช้เมื่อวัตถุไม่ได้เปิดใช้งาน นำมาใช้ในAPI ระดับ 11

ฉันคิดว่าเอกสารค่อนข้างชัดเจนปัญหาคืออะไร


5
คุณสามารถอธิบายเกี่ยวกับ android: state_selected อะไรคือสถานการณ์เมื่อถูกตั้งค่าเป็นจริง?
Anderson

@ แอนเดอร์สันมันจะขึ้นอยู่กับ ViewGroup ที่คุณกำลังใช้ - ListView, RecyclerView (อาจเป็น LayoutManagers), GridView อาจมีการใช้งานที่แตกต่างกัน: การเรียก ListView setFocused ที่ GridView เรียก setSelected เป็นต้น อาจเป็นเพียงกรณีของการตรวจสอบแอปของคุณบนแพลตฟอร์มเวอร์ชันต่างๆ
ataulm

1
@ แอนเดอร์สัน: หากคุณมีรายการและผู้ใช้มีปุ่มลูกศรปุ่มหนึ่งคือ "เลือก" และเมื่อพวกเขาลูกศรขึ้น / ลงการเลือกจะเลื่อนขึ้น / ลง เมื่อพวกเขากดปุ่ม "เปิดใช้งาน" มันจะ "เปิดใช้งาน" การควบคุมให้คิดว่าการเลือกนั้นคลุมเครือคล้ายกับการวางเมาส์เหนือและตรวจสอบ / เปิดใช้งานเหมือนกับการคลิก
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;
    }
    }
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.