OnItemCLickListener nie działa w widoku listy


243

Activity kod klasowy:

conversationList = (ListView)findViewById(android.R.id.list);
ConversationArrayAdapter conversationArrayAdapter=new  ConversationArrayAdapter(this, R.layout.conversation_list_item_format_left, conversationDetails);
conversationList.setAdapter(conversationArrayAdapter);
conversationList.setOnItemClickListener(new AdapterView.OnItemClickListener(){ 
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
        Log.d("test","clicked");
    }
});

getViewFunkcji w Adapterklasie:

if (v == null) {                                
    LayoutInflater vi = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if(leftSideMessageNumber.equals(m.getTo())) {
        v = vi.inflate(R.layout.conversation_list_item_format_left, null);
    } else {
        v = vi.inflate(R.layout.conversation_list_item_format_right, null);
    }
}

Czy jest problem z użyciem dwóch plików XML podczas pompowania?


4
@hiei Mój problem polegał na tym, że używałem przycisków graficznych w komórkach układu. Nawet po dodaniu „android: descendantFocusability” mój odbiornik kliknięć nie odpowiadał. Zrobiłem to, zmieniłem wszystkie ImaegButtons na ImageViews. To rozwiązało mój problem.
Ajith Memana,

Odpowiedzi:


731

Właśnie znalazłem rozwiązanie stąd, ale poprzez głębokie kliknięcie.

Jeśli jakikolwiek element listy na liście zawiera widok z możliwością zogniskowania lub klikalny OnItemClickListener, nie będzie działać.

Element wiersza musi mieć parametr podobny do parametru android:descendantFocusability = "blocksDescendants".

Tutaj możesz zobaczyć przykładowy wygląd elementu listy. Element listy xml powinien być ... row_item.xml( your_xml_file.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:baselineAligned="false"
    android:descendantFocusability="blocksDescendants"
    android:gravity="center_vertical" >

    // your other widgets here

</LinearLayout>

nie działa dla mnie. Czy ktoś może spojrzeć na [ stackoverflow.com/questions/21692209/…
suitianshi

3
Możesz również ustawić to programowo za pomocą listView.setDescendantFocusability(int focus);gdzie focusjest jeden ViewGroup.FOCUS_BEFORE_DESCENDANTS, ViewGroup.FOCUS_AFTER_DESCENDANTSlubViewGroup.FOCUS_BLOCK_DESCENDANTS
Max Worg

Myślę, że to zabawne, że jak 20 osób podziękowało w komentarzu. Napotykałem ten problem przez ostatnie 8 godzin, bardzo dziękuję za to.
sparticvs

1
Moje pytanie brzmi: to jest błąd Androida, czy to z założenia?
fangzhzh

Utknąłem w tym od 6 godzin i naprawdę potrzebuję pomocy. stackoverflow.com/questions/35108940/why-cant-i-remove-an-item/…
Ruchir Baronia

89

Problem polega na tym, że Twoje układy zawierają elementy, które można aktywować lub klikalne. Jeśli widok zawiera element, na którym można ustawić fokus lub klikalny element, OnItemCLickListener nie zostanie wywołany.

Kliknij tutaj, aby uzyskać więcej informacji.

Opublikuj jeden z plików XML swojego układu, jeśli tak nie jest.


2
To było dla mnie rozwiązanie. Zadeklarowałem swój pogląd jako klikalny. Dzięki!
kingraam

1
Dzięki! Zmieniłem moje 2 EditTexts na TextViews i CheckBoxpozwolono pozostać (i pozostać w stanie przełączalnym) z android:descendantFocusability="blocksDescendants"dodanym do mojego LinearLayout.
Azurespot

Tak! Miałem android:focusableInTouchMode="true"wiersz, po usunięciu zaczął w końcu działać! :-)
SharpC

58

W przypadku moich list moje wiersze zawierają inne rzeczy, które można kliknąć, takie jak przyciski, więc robienie koca blocksDescendantsnie działa. Zamiast tego dodałem wiersz w xml przycisku:

android:focusable="false"

To powstrzymuje przyciski przed blokowaniem kliknięć w wierszach, ale nadal pozwala przyciskom na klikanie.


@ user1840899 To jest częsta odpowiedź, z której się nauczyłem, więc ją przekazałem. To poprawna informacja, nie warta głosowania w dół.
Janene Pappas

Działa to dla mnie na pole wyboru w pozycji ListView (bez blocksDescendants)
thpitsch

To naprawia błąd, utrzymując klikalność przycisków (ToggleButton dla mnie)
Mohsen Afshin

Jedynym sposobem, w jaki mogłem uzyskać GridView z działającymi RadioButtonami, było zastosowanie Androida: descendantFocusability = "blocksDescendants" na LinearLayout zawierający RadioButton, i poprzez ustawienie androida: clickable = "false" w samym RadioButton.
Stephen McCormick

Utknąłem w tym od 6 godzin i naprawdę potrzebuję pomocy. stackoverflow.com/questions/35108940/why-cant-i-remove-an-item/…
Ruchir Baronia

34

musisz wykonać 2 kroki w pliku listview_item.xml

  1. ustaw układ główny za pomocą: android:descendantFocusability="blocksDescendants"
  2. ustaw w tym elemencie dowolny widok z możliwością aktywacji lub klikalny:
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="false"

Oto przykład: listview_item.xml

<?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="wrap_content"
    android:layout_marginBottom="10dp"
    android:layout_marginTop="10dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:descendantFocusability="blocksDescendants">

    <RadioButton
        android:id="@+id/script_name_radio_btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textColor="#000"
        android:padding="5dp"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        />

</LinearLayout>

Ustawienie clickable="truew widoku elementu spowoduje, że onItemClicknie będzie wywoływany. clickable="false"LinearLayout
Zwróć

Ustawienie Androida: descendantFocusability = "blocksDescendants" pomaga mi. Dzięki!
LLIAJLbHOu

21.12.2016, a po godzinach poszukiwań TO działało, dzięki człowieku!
Tanner Summers

Jeśli masz taki sam układ jak krajobraz, itp., Upewnij się, że również to robisz.
Immy,

19

użyj poniższego kodu wewnątrz znacznika przycisku w niestandardowym układzie wiersza widoku listy

 android:focusable="false"
 android:clickable="false"

Świetny człowiek, to było naprawdę pomocne !!
divyansh ingle

to działało tutaj !! Mam wiele pól wyboru w tym widoku i próbuję android:descendantFocusability="blocksDescendants"zablokować to pole wyboru dla kliknięcia
Armando Marques Sobrinho

17

Miałem ten sam problem i właśnie zobaczyłem, że przypadkowo ustawiłem:

@Override
public boolean isEnabled(int position)
{
    return false;
}

w mojej klasie CustomListViewAdapter.

Zmieniając to na:

return true;

Udało mi się rozwiązać problem. Na wypadek, gdyby ktoś popełnił ten sam błąd ...


7
Ja też miałem@Override public void onApplicationStart { ExplodeThisDevice(); }
Léon Pelletier

17

Użyj Androida: descendantFocusability

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dip"
    android:background="@color/light_green"
    android:descendantFocusability="blocksDescendants" >

Dodaj powyżej w układzie głównym


2
Dodanie szczegółów może sprawić, że będzie to lepsza odpowiedź i +1.
Killer

To działało dla mnie i mój przycisk w elemencie listy działał nadal zgodnie z przeznaczeniem.
Gustav Eriksson


10

jeśli masz widoki tekstu, przyciski lub stg, które można kliknąć lub wybrać tylko w widoku wiersza

android:descendantFocusability="blocksDescendants"

nie wystarcza. Musisz ustawić

android:textIsSelectable="false"

do twoich tekstów i

android:focusable="false"

do przycisków i innych przedmiotów, na które można ustawić ostrość.


Nauczyłem się tego na własnej skórze. android: textIsSelectable = "false" Pilnuj tego :)
diyoda_

10

Nawet ja miałem ten sam problem, mam pole wyboru, wykonałem następujące czynności, aby zamaskować element itemClickListener,

Dodano następujące właściwości do pola wyboru,

android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"

i ItemClickListner zaczął działać.

Aby uzyskać szczegółowy przykład, możesz przejść przez link,

http://knowledge-cess.com/android-itemclicklistner-with-checkbox-or-radiobutton/

Mam nadzieję, że to pomaga na zdrowie !!


5

Miałem ten sam problem i wypróbowałem wszystkie wymienione rozwiązania bezskutecznie. dzięki testom odkryłem, że umożliwienie wyboru tekstu uniemożliwiało wywołanie słuchacza. Więc zmieniając go na false lub usuwając go, mój słuchacz został ponownie wywołany.

android:textIsSelectable="false"

Mam nadzieję, że to pomoże komuś, kto utknął jak ja.


4
  1. Dodaj to w głównym układzie

    android:descendantFocusability="blocksDescendants"
  2. Napisz ten kod do każdego przycisku, Textview, ImageView itp., Które mają onClick

    android:focusable="false"
    
    android:clickable="false"

Mam nadzieję, że to zadziała.


3

Dwa niesamowite rozwiązania były takie: jeśli rozszerzając ListFragment z fragmentu, wiesz, że mListView.setOnItemClickListenernie zostanie wywołany przed utworzeniem działania, zapewniło to ustawienie, gdy działanie zostało utworzone

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mListView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
            // Do the onItemClick action

            Log.d("ROWSELECT", "" + rowId);
        }
    });
}

Przeglądając kod źródłowy ListFragment, natknąłem się na to

public class ListFragment extends Fragment {
    ...........................................
    ................................................

    final private AdapterView.OnItemClickListener mOnClickListener
                = new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            onListItemClick((ListView)parent, v, position, id);
        }
    };

    ................................................................
    ................................................................

    public void onListItemClick(ListView l, View v, int position, long id) {
    }
}

onItemClickListenerObiekt jest przymocowany i wywołuje onListItemClick() Jako taka innego podobnego rozwiązania, które działa w dokładnie taki sam sposób jest ręcznymonListItemClick()

@Override
public void onListItemClick(ListView l, View v, int position, long rowId) {
    super.onListItemClick(l, v, position, id);
   // Do the onItemClick action

   Log.d("ROWSELECT", "" + rowId);
} 

3

w moim przypadku żadna z właściwości układu xml nie była pomocna.

Dodaję tylko jeden wiersz kodu w ten sposób: convertView.setClickable (false);

@NonNull
@Override
public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
    ViewHolder viewHolder;
    if (convertView == null || convertView.getTag() == null) {
        LayoutInflater inflater = LayoutInflater.from(context);
        convertView = inflater.inflate(R.layout.my_layout_id, parent, false);
        viewHolder = new ViewHolder(convertView);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    ...
    convertView.setClickable(false);
    return convertView;
}

więc w zasadzie robi to samo, co konfigurowanie właściwości w układzie xml, ale w moim przypadku było to jedyne, co działa.

To nie jest idealne wyczucie czasu, ale może pomoże komuś w kodowaniu


1

Próbowałem wszystkich powyższych i NIC nie działało.

Rozwiązałem problem w następujący sposób:

Najpierw zdefiniuję niestandardowy przycisk o nazwie ListButton

public class ListButton extends android.widget.Button
{

private ButtonClickedListener clickListener;

public ListButton(Context context)
{
    this(context, null);
}

public ListButton(Context context, AttributeSet attrs)
{
    this(context, attrs, 0);
}

public ListButton(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
}

public void setClickListener(ButtonClickedListener listener) {
    this.clickListener = listener;
}

@Override
public boolean isInTouchMode() {
    return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    return false;
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    switch (event.getAction()) 
      {
          case MotionEvent.ACTION_DOWN:
              break;
          case MotionEvent.ACTION_UP:

              eventClicked();

              break;
          case MotionEvent.ACTION_CANCEL:
              break;
          case MotionEvent.ACTION_MOVE:
              break;
          default :

      }
    return true;
}

private void eventClicked() {
    if (this.clickListener!=null) {
        this.clickListener.ButtonClicked();
    }
}

}

XML wygląda następująco:

<dk.example.views.ListButton
android:id="@+id/cancel_button"
android:layout_width="125dp"
android:layout_height="80dp"
android:text="Cancel"
android:textSize="20sp" 
android:layout_margin="10dp"
android:padding="2dp"
android:background="#000000"
android:textColor="#ffffff"
android:textStyle="bold"  
/>

Następnie definiuję własny ButtonClickedinterfejs Listenera:

public interface ButtonClickedListener {
    public void ButtonClicked();
}

Następnie używam własnego odbiornika, tak jakby to był normalny OnClickListener:

final ListButton cancelButton = (ListButton) viewLayout.findViewById(R.id.cancel_button);

    cancelButton.setClickListener(new ButtonClickedListener() {

        @Override
        public void ButtonClicked() {
            //Do your own stuff here...
        }

    });

1

Miałem ten sam problem, użyłem stylu dla moich tekstów w układzie wierszy, który miał atrybut „do zogniskowania”. Działa po tym, jak go usunąłem.


1

W moim przypadku musiałem usunąć następny wiersz z Layout

android:clickable="true"


0

Jeśli chcesz użyć zarówno prostego kliknięcia, jak i długiego kliknięcia, zobacz elementy listy, lepszym sposobem na wdrożenie jest użycie menu kontekstowego dla długiego kliknięcia. Unikaj używania setItemLongClickListener, szczególnie jeśli masz wiele układów wierszy dla widoku listy.


0

W obliczu tego samego problemu, próbowany przez wiele godzin. Jeśli wypróbowałeś wszystkie powyższe, spróbuj zmienić układ_widoku widoku listy i elementu listy na match_parent z wrap_content.


0

Wszystkie powyższe zawiodły dla mnie. Jednak udało mi się rozwiązać problem (po wielu godzinach walenia głową - Google, jeśli słuchasz, rozważ naprawienie tego, co napotkałem poniżej, w postaci błędów kompilatora, jeśli to możliwe)

Naprawdę musisz uważać na to, jakie atrybuty Androida dodajesz tutaj do swojego układu xml (w tym oryginalnym pytaniu nazywa się to list_items.xml). Dla mnie problem polegał na tym, że przełączyłem się z widoku EditText na TextView i miałem resztkowy atrybut cruft po zmianie (w moim przypadku inputType). Kompilator go nie złapał, a klikalność po prostu się nie udała, kiedy poszedłem uruchomić aplikację. Dokładnie sprawdź wszystkie atrybuty, które masz w swoich węzłach xml układu.


0
private AdapterView.OnItemClickListener onItemClickListener;

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
 .......

final View view = convertView;
convertView.setOnClickListener(new View.OnClickListener() {
    @Override
     public void onClick(View v) {
         if (onItemClickListener != null) {
             onItemClickListener.onItemClick(null, view, position, -1);
         }
      }
 });

return convertView;
}

public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

Następnie w swojej działalności użyj adapter.setOnItemClickListener () przed dołączeniem go do widoku listy.

Skopiowane z github działało dla mnie


0

Rzeczą, która działała dla mnie, było dodanie poniższego kodu do każdego widoku podrzędnego w układzie mojego pliku row.xml:

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

Więc w moim przypadku:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:id="@+id/testingId"
        android:text="Name"
       //other stuff 
        />

    <TextView
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:id="@+id/dummyId"
        android:text="icon"
        //other stuff 
        />

    <TextView
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:id="@+id/assignmentColor"
       //other stuff 
       />

    <TextView
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:id="@+id/testID"
        //other stuff 
        />

    <TextView
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:text="TextView"
        //other stuff 
        />

</android.support.constraint.ConstraintLayout>

Oto moje wywołanie setOnItemClickListener w mojej podklasie Fragment:

CustomListView = (PullToRefreshListCustomView) layout.findViewById(getListResourceID());
        CustomListView.setAdapter(customAdapter);
        CustomListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Log.d("Testing", "onitem click working");
              //  other code
            }

        });

Mam stąd odpowiedź !


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.