ปัญหาการคลิก ListView แบบกำหนดเองบนรายการใน Android


110

ดังนั้นฉันจึงมีวัตถุ ListView ที่กำหนดเอง รายการมีมุมมองข้อความสองรายการซ้อนกันอยู่ด้านบนของแต่ละรายการรวมทั้งแถบความคืบหน้าแนวนอนที่ฉันต้องการซ่อนไว้จนกว่าฉันจะทำอะไรบางอย่างจริงๆ ทางด้านขวาสุดคือช่องทำเครื่องหมายที่ฉันต้องการแสดงเฉพาะเมื่อผู้ใช้ต้องการดาวน์โหลดการอัปเดตไปยังฐานข้อมูลของตนเท่านั้น เมื่อฉันปิดใช้งานช่องทำเครื่องหมายโดยตั้งค่าการมองเห็นเป็น Visibility GONE ฉันสามารถคลิกที่รายการได้ เมื่อมองเห็นช่องทำเครื่องหมายฉันไม่สามารถคลิกสิ่งใดในรายการได้ยกเว้นช่องทำเครื่องหมาย ฉันได้ทำการค้นหา แต่ไม่พบอะไรที่เกี่ยวข้องกับสถานการณ์ปัจจุบันของฉัน เจอคำถามนี้แต่ฉันใช้ ArrayAdapter ที่ถูกแทนที่เนื่องจากฉันใช้ ArrayLists เพื่อเก็บรายการฐานข้อมูลไว้ภายใน ฉันต้องได้รับมุมมอง LinearLayout และเพิ่ม onClickListener เหมือน Tom หรือไม่ ฉันไม่แน่ใจ.

นี่คือ XML เค้าโครงแถว listview:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/UpdateNameText"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_vertical"
            />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:id="@+id/UpdateStatusText"
            android:singleLine="true"
            android:ellipsize="marquee"
            />
        <ProgressBar android:id="@+id/UpdateProgress" 
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content"
                     android:indeterminateOnly="false" 
                     android:progressDrawable="@android:drawable/progress_horizontal" 
                     android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" 
                     android:minHeight="10dip" 
                     android:maxHeight="10dip"                    
                     />
    </LinearLayout>
    <CheckBox android:text="" 
              android:id="@+id/UpdateCheckBox" 
              android:layout_width="wrap_content" 
              android:layout_height="wrap_content" 
              />
</LinearLayout>

และนี่คือคลาสที่ขยาย ListActivity เห็นได้ชัดว่ามันยังอยู่ในระหว่างการพัฒนาดังนั้นจงให้อภัยในสิ่งที่ขาดหายไปหรืออาจจะถูกทิ้งไว้รอบ ๆ :

public class UpdateActivity extends ListActivity {

    AccountManager lookupDb;
    boolean allSelected;
    UpdateListAdapter list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lookupDb = new AccountManager(this);
        lookupDb.loadUpdates();

        setContentView(R.layout.update);
        allSelected = false;

        list = new UpdateListAdapter(this, R.layout.update_row, lookupDb.getUpdateItems());
        setListAdapter(list);

        Button btnEnterRegCode = (Button)findViewById(R.id.btnUpdateRegister);
        btnEnterRegCode.setVisibility(View.GONE);

        Button btnSelectAll = (Button)findViewById(R.id.btnSelectAll);
        btnSelectAll.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                allSelected = !allSelected;

                for(int i=0; i < lookupDb.getUpdateItems().size(); i++) {
                    lookupDb.getUpdateItem(i).setSelected(!lookupDb.getUpdateItem(i).isSelected());
                }

                list.notifyDataSetChanged();
                // loop through each UpdateItem and set the selected attribute to the inverse 

            } // end onClick
        }); // end setOnClickListener

        Button btnUpdate = (Button)findViewById(R.id.btnUpdate);
        btnUpdate.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
            } // end onClick
        }); // end setOnClickListener

        lookupDb.close();
    } // end onCreate


    @Override
    protected void onDestroy() {
        super.onDestroy();

        for (UpdateItem item : lookupDb.getUpdateItems()) {
            item.getDatabase().close();        
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        UpdateItem item = lookupDb.getUpdateItem(position);

        if (item != null) {
            item.setSelected(!item.isSelected());
            list.notifyDataSetChanged();
        }
    }

    private class UpdateListAdapter extends ArrayAdapter<UpdateItem> {
        private List<UpdateItem> items;

        public UpdateListAdapter(Context context, int textViewResourceId, List<UpdateItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = null;

            if (convertView == null) {
                LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = li.inflate(R.layout.update_row, null);
            } else {
                row = convertView;
            }

            UpdateItem item = items.get(position);

            if (item != null) {
                TextView upper = (TextView)row.findViewById(R.id.UpdateNameText);
                TextView lower = (TextView)row.findViewById(R.id.UpdateStatusText);
                CheckBox cb = (CheckBox)row.findViewById(R.id.UpdateCheckBox);

                upper.setText(item.getName());
                lower.setText(item.getStatusText());

                if (item.getStatusCode() == UpdateItem.UP_TO_DATE) {
                    cb.setVisibility(View.GONE);
                } else {
                    cb.setVisibility(View.VISIBLE);
                    cb.setChecked(item.isSelected());
                }

                ProgressBar pb = (ProgressBar)row.findViewById(R.id.UpdateProgress);
                pb.setVisibility(View.GONE);
            }
            return row;
        }

    } // end inner class UpdateListAdapter
}

แก้ไข: ฉันยังคงประสบปัญหานี้ ฉันกำลังโกงและเพิ่มตัวจัดการ onClick ใน textviews แต่ดูเหมือนว่าโง่มากที่ฟังก์ชัน onListItemClick () ของฉันไม่ถูกเรียกเลยเมื่อฉันไม่ได้คลิกที่ช่องทำเครื่องหมายของฉัน

คำตอบ:


243

ปัญหาคือ Android ไม่อนุญาตให้คุณเลือกรายการที่มีองค์ประกอบที่สามารถโฟกัสได้ ฉันแก้ไขช่องทำเครื่องหมายในรายการให้มีแอตทริบิวต์ดังนี้:

android:focusable="false"

ตอนนี้รายการของฉันที่มีช่องทำเครื่องหมาย (ใช้งานได้กับปุ่มด้วย) เป็นแบบ "เลือกได้" ในความหมายดั้งเดิม (สว่างขึ้นคุณสามารถคลิกที่ใดก็ได้ในรายการและตัวจัดการ "onListItemClick" จะเริ่มทำงานเป็นต้น)

แก้ไข: ในการอัปเดตผู้แสดงความคิดเห็นกล่าวว่า "เพียงบันทึกหลังจากเปลี่ยนการเปิดเผยปุ่มฉันต้องปิดการใช้งานโฟกัสโดยใช้โปรแกรมอีกครั้ง"


24
ปรากฏโซลูชันนี้ใช้ไม่ได้เมื่อใช้ ImageButton ในรายการ :(
Julian A.

1
โอเค แต่ถ้าฉันต้องการให้ช่องทำเครื่องหมายและมุมมองรายการของฉันคลิกเป็นเอกสิทธิ์เฉพาะบุคคลล่ะ หากฉันเลือกรายการมุมมองรายการฉันไม่จำเป็นต้องตรวจสอบกล่องกาเครื่องหมาย วิธีนี้เป็นไปได้หรือไม่?
Mike6679

@ ไมค์ใช่วิธีแก้ปัญหานี้ยังคงต้องมีการคลิกช่องทำเครื่องหมายอย่างชัดเจนเพื่อที่จะโต้ตอบได้ เพียงแค่เปิดใช้งานฟังก์ชันใน ListView อีกครั้งซึ่งจะข้ามไปอย่างลึกลับเมื่อคุณมีองค์ประกอบที่โฟกัสได้ในเค้าโครงรายการของคุณ
MattC

2
ขอบคุณคำตอบที่ดีใช้ได้ดีกับ ImageButtons ด้วย เพียงทราบว่าหลังจากเปลี่ยนการมองเห็นของปุ่มฉันต้องปิดการใช้งานโฟกัสโดยโปรแกรมอีกครั้ง
Ljdawson

1
คุณอาจต้องตั้งค่า android: clickable = "false"
Mina Samy

43

ในกรณีที่คุณมี ImageButton ภายในรายการคุณควรตั้งdescendantFocusabilityค่าเป็น 'blocksDescendants' ในองค์ประกอบรายการรูท

android:descendantFocusability="blocksDescendants"

และfocusableInTouchModeแฟล็กไปtrueในImageButtonมุมมอง

android:focusableInTouchMode="true"

1
ใช้งานได้ดีสำหรับ listitem ที่มี imagebuttons แต่อาจใช้งานได้ยกเว้น ImageButton
raksja

12

ฉันมีปัญหาที่คล้ายกันเกิดขึ้นและพบว่า CheckBox ค่อนข้างจู้จี้จุกจิกใน ListView สิ่งที่เกิดขึ้นคือมันกำหนดว่าจะอยู่ใน ListItem ทั้งหมดและประเภทของการลบล้าง onListItemClick คุณอาจต้องการใช้ตัวจัดการการคลิกสำหรับสิ่งนั้นและตั้งค่าคุณสมบัติข้อความสำหรับกล่องกาเครื่องหมายเช่นกันแทนที่จะใช้ TextViews

ฉันจะบอกว่าดูวัตถุ View นี้ด้วยมันอาจทำงานได้ดีกว่า CheckBox

มุมมองข้อความที่เลือก


6
เราพบว่าหากคุณตั้งค่า "โฟกัสได้" เป็นเท็จสำหรับรายการที่โฟกัสได้ในรายการคุณสามารถใช้ฟังก์ชัน onListItemClick ของคุณได้อีกครั้ง
MattC

2
อย่างไรก็ตามช่องทำเครื่องหมายจะเปลี่ยนเป็นสีส้มเหมือนรายการ ใครรู้วิธีแก้ปัญหา?
erdomester

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.