Làm thế nào để kích hoạt onListItemClick trong Listactivity với các nút trong danh sách?


89

Tôi có một ListActivity đơn giản sử dụng ListAdapter tùy chỉnh để tạo các dạng xem trong danh sách. Thông thường ListAdapter sẽ chỉ lấp đầy các khung nhìn bằng TextView, nhưng bây giờ tôi cũng muốn đặt một nút ở đó.

Tuy nhiên, theo sự hiểu biết và kinh nghiệm của tôi, việc đặt chế độ xem có thể lấy tiêu điểm trong mục danh sách ngăn chặn việc kích hoạt onListItemClick () trong ListActivity khi mục danh sách được nhấp. Nút vẫn hoạt động bình thường trong mục danh sách, nhưng khi một thứ gì đó ngoài nút được nhấn, tôi muốn kích hoạt onListItemClick.

Làm thế nào tôi có thể làm cho nó hoạt động?


5
giải pháp của bạn với Focusability con cháu thực sự hữu ích, bạn nên thêm nó làm câu trả lời và chấp nhận nó!
Maksym Gontar

@Max Lý do tôi không làm là vì nó thực sự không tốt, một cách giải quyết. Nếu tôi đã từng tìm thấy một giải pháp cho sức khỏe vĩnh viễn tôi sẽ làm điều đó một câu trả lời (nếu tôi nhớ rằng tôi đã viết câu hỏi này một năm trước đây :))
CodeFusionMobile

Tôi cũng muốn xem cách giải quyết khác mà bạn có. Tôi đã cố gắng đặt tiêu điểm con và không thể làm cho nó hoạt động với các nút. Ngoài ra, tôi đã cố gắng đặt GridView (có ImageViews) vào hàng danh sách và điều đó cũng gặp phải vấn đề tương tự.
MrPurpleStreak

Câu trả lời IMHO mà tôi đưa ra là giải pháp thanh lịch hơn nhiều cho vấn đề sau đó là giải pháp do Ramps và Praveen đề xuất. PsKhông cố gắng hồi sinh câu hỏi bị lãng quên ở đây nhưng tôi thấy bạn vẫn chưa chấp nhận bất kỳ câu trả lời nào; D
Ewoks

@CodeFusionMobile Bạn có thể chấp nhận câu trả lời của Ewoks không? Câu trả lời được bình chọn cao nhất là thiếu sót vì nó vô hiệu hóa hoạt ảnh onclick cho phần tử ListView (nơi nó chuyển sang màu xanh lam). Nó sẽ tiết kiệm cho các nhà phát triển khác một khoảng thời gian để thử câu trả lời hàng đầu, phát hiện ra rằng nó còn thiếu sót, và sau đó chuyển sang của Ewoks.
1 ''

Câu trả lời:


99

như tôi đã viết trong giải pháp nhận xét trước đó là setFocusable (false) trên ImageButton.

Thậm chí còn có một giải pháp thanh lịch hơn, hãy thử thêm android:descendantFocusability="blocksDescendants" vào bố cục gốc của phần tử danh sách. Điều đó sẽ làm cho các lần nhấp trênListItem có thể thực hiện được và riêng bạn có thể xử lý các lần nhấp vào Nút hoặc Hình ảnh

Hy vọng nó giúp ;)

Chúc mừng


3
android:descendantFocusability="blocksDescendants"Hoàn hảo.
Matthew Mitchell

1
bạn, bạn của tôi, là anh hùng của riêng tôi. bạn nên là người được bình chọn hàng đầu! điều này tốt hơn nhiều cho hầu hết mọi trường hợp!
OschtärEi

Đây phải là câu trả lời được chấp nhận. Nó làm việc hoàn hảo cho tôi. Có vẻ như tất cả các chế độ xem trong mục danh sách cần phải không tập trung và chế độ này thực hiện điều đó mà không cần thiết lập từng chế độ riêng lẻ.
hối hả vào

1
Điều này dường như không hiệu quả với tôi. Theo bố cục gốc, bạn có nghĩa là bố cục hàng hoặc nơi chế độ xem danh sách được xác định? Nhưng dù sao, tôi đã thử tất cả các kết hợp có thể .. không hoạt động :(
GreenBee

"Root bố trí của nguyên tố danh sách" như tôi đã viết .. Vì vậy, giả sử bạn có danh sách và bao gồm bố trí (gọi họ là bố trí gốc của nguyên tố danh sách) mà có một vài Button, ImageButton, TextVeiw ..
Ewoks

59

Tôi hy vọng tôi có thể giúp đỡ ở đây. Tôi giả sử rằng bạn có bố cục tùy chỉnh cho các mục listView và bố cục này bao gồm nút và một số chế độ xem khác - như TextView, ImageView hoặc bất cứ thứ gì. Bây giờ bạn muốn có sự kiện khác nhau được kích hoạt khi nhấp vào nút và sự kiện khác được kích hoạt trên mọi thứ khác được nhấp.

Bạn có thể đạt được điều đó mà không cần sử dụng onListItemClick () của ListActivity.
Đây là những gì bạn phải làm:

Bạn đang sử dụng bố cục tùy chỉnh, vì vậy có thể bạn đang ghi đè phương thức getView () từ bộ điều hợp tùy chỉnh của mình. Bí quyết là đặt những người nghe khác nhau cho nút của bạn và khác nhau cho toàn bộ chế độ xem (hàng của bạn). Hãy xem ví dụ:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

Lớp OnItemClickListener của bạn có thể được khai báo như sau:

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

Tất nhiên, bạn có thể sẽ thêm một số tham số nữa vào hàm tạo OnItemClickListener.
Và một điều quan trọng - việc triển khai getView được hiển thị ở trên khá xấu, thông thường bạn nên sử dụng mẫu ViewHolder để tránh các cuộc gọi findViewById .. nhưng có thể bạn đã biết điều đó.
Tệp custom_row.xml của tôi là RelativeLayout với Nút của id "button", TextView của id "text" và ImageView của id "image" - chỉ để làm rõ mọi thứ.
Trân trọng!


9
Giải pháp của tôi cuối cùng đã đi theo một hướng khác. Tôi đã giải quyết vấn đề bằng cách đặt thuộc tính Focusability con cháu của bố cục hàng danh sách để chặn con cháu và đột nhiên nó hoạt động. Bây giờ tôi sử dụng một simpleCursorAdapter với một khung nhìn tùy chỉnh được gắn vào nó để thiết lập sự kiện và những thứ lạ mắt khác liên quan đến các nút.
CodeFusionMobile

3
Tôi đã sử dụng giải pháp này. Tuy nhiên, một cảnh báo: nếu trình xử lý onClick của bạn khiến nội dung của danh sách thay đổi, điều này sẽ dẫn đến việc getView được gọi là VÀ nếu tiện ích của bạn là trạng thái (như ToggleButton hoặc CheckBox), VÀ getView đặt trạng thái đó, bạn có thể muốn setOnClickListener (null) trước khi bạn thay đổi trạng thái trong onView, để tránh nhận được hiệu ứng vòng lặp.
Pierre-Luc Paour

3
những gì về giải pháp của tôi? Tôi có ấn tượng rằng là thanh lịch hơn và có thể được áp dụng dễ dàng hơn bất cứ khi nào chúng ta cần nó ..
Ewoks

những nhận xét đầu tiên nên được chấp nhận như là câu trả lời, vì vậy những người như tôi sẽ không cần thời gian để tìm nó
keybee

Cảm ơn! Điều này rất hữu ích. Tôi thích nó như một sự thay thế được bản địa hóa hơn cho phương pháp tiếp cận focus: blockDescendants được mô tả trong các chủ đề khác.
Yoav Shapira

18

Khi một ListView tùy chỉnh chứa các phần tử có thể lấy tiêu điểm, onListItemClick sẽ không hoạt động (tôi nghĩ đó là hành vi mong đợi). Chỉ cần xóa tiêu điểm khỏi chế độ xem tùy chỉnh, nó sẽ thực hiện thủ thuật:

Ví dụ:

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
               
    }
}

3
Tôi thích giải pháp của bạn: nếu chỉ có một tiện ích con "có thể nhấp" trên mỗi hàng, thì việc từ chối khả năng lấy nét của chúng là một giải pháp thanh lịch. Điều đó có nghĩa là một lần nhấn ở bất kỳ vị trí nào trên hàng sẽ khớp, nhưng đó là một hành vi hữu ích khi tiện ích con là radio hoặc hộp kiểm. Điều tương tự cũng có thể đạt được trong XML bằng cách sử dụng android: focusable = "false" và android: focusableInTouchMode = "false".
Pierre-Luc Paour

1
cách xml dường như không làm việc nếu bạn thay đổi tầm nhìn, vì vậy người ta phải làm điều đó thông qua các mã sau khi cài đặt "View" để có thể nhìn thấy
max4ever

13

Tôi gặp vấn đề tương tự: OnListItemClick không được kích hoạt! [SOLVED]
Điều đó xảy ra trên lớp mở rộng ListActivity,
với bố cục cho ListActivity có nội dung TextBox và ListView được lồng vào LinearLayout
và bố cục khác cho các hàng (CheckBox và TextBox được lồng vào LineraLayout).

Đó là mã:

res / layout / configpage.xml (chính cho ListActivity)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" > 
    <TextView  
        android:id="@+id/selection"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="pippo" /> 
    <ListView  
        android:id="@android:id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:drawSelectorOnTop="false"  
        android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"> 
  <CheckBox  
      android:id="@+id/img"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 

  <TextView  
      android:id="@+id/testo"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ ConfigPage.java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

Điều này bắt đầu hoạt động khi tôi thêm vào row.xml

  • android:focusable="false"
  • android:focusableInTouchMode="false"

Tôi sử dụng Eclipse 3.5.2
Android
SDK phiên bản SDK 10.0.1 phút: 3

Tôi hy vọng điều này hữu ích
... và xin lỗi vì tiếng anh của tôi :(


@fellons không biết tại sao, nhưng nó không hoạt động với tôi. OnListItemClick của tôi không được gọi.
likejudo

Bạn đã thêm mã thuộc tính android: focusable = "false" và mã android: focusableInTouchMode = "false" chưa?
rfellons

2

chỉ cần thêm android:focusable="false"làm một trong những thuộc tính của nút của bạn


1

Tôi đã gặp vấn đề tương tự với ToggleButton. Sau nửa ngày đập đầu vào tường cuối cùng tôi cũng giải được. Nó đơn giản như làm cho chế độ xem có thể lấy nét không thể lấy nét được bằng cách sử dụng 'android: focusable'. Bạn cũng nên tránh chơi với khả năng tập trung và khả năng nhấp (tôi chỉ tạo từ) của hàng danh sách, chỉ để chúng với giá trị mặc định.

Tất nhiên, bây giờ các chế độ xem có thể lấy tiêu điểm của bạn trong hàng danh sách không thể lấy tiêu điểm, người dùng sử dụng bàn phím có thể gặp sự cố, tốt khi lấy nét chúng. Nó có thể không phải là vấn đề, nhưng chỉ trong trường hợp bạn muốn viết 100% ứng dụng hoàn hảo, bạn có thể sử dụng sự kiện onItemSelected để làm cho các phần tử của hàng đã chọn có thể lấy tiêu điểm và các phần tử của hàng đã chọn trước đó không thể lấy tiêu điểm.


Tôi đã sử dụng cách tiếp cận này. Đó là cách đơn giản nhất, nếu bạn có thể giải quyết vấn đề không thể tập trung vào từng mục riêng lẻ. Điều này cũng giữ trạng thái có thể kéo được cho các mục danh sách như bình thường, điều mà một số cách giải quyết khác không làm được.
Jonathan S.

1
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});

-1

Tôi đã sử dụng getListAdapter (). GetItem (position) khởi tạo một Đối tượng chứa các giá trị của tôi trong mục

MyPojo myPojo = getListAdapter().getItem(position);

sau đó sử dụng phương thức getter từ myPojo nó sẽ gọi các giá trị thích hợp của nó trong mục.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.