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?

cześć
źródło
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>
Bhavesh Hirpara
źródło
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.

balazsbalazs
źródło
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.

Janene Pappas
źródło
@ 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>
Wir
źródło
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"
Milan Shukla
źródło
Ś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 ...

Drzewiasty
źródło
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

Amar Gore
źródło
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
11

Rozwiązałem to za pomocą tej odpowiedzi

1. Dodaj następujące elementy w Układ liniowy list_items.xml android:descendantFocusability="blocksDescendants"

2. Widoki dla dzieci LinearLayout w list_items.xml

 android:focusable="false" 
RAJESH KUMAR ARUMUGAM
źródło
Twój link jest uszkodzony.
Jason C
1
@JasonC Dzięki za informacje. Oto link stackoverflow.com/a/14915758/5740760
RAJESH KUMAR ARUMUGAM
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ść.

populacja
źródło
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 !!

Gokul Kulkarni
źródło
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.

u2tall
źródło
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.

Wajid Khan
źródło
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);
} 
Rowland Mtetezi
źródło
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

Marek Skóra
źródło
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...
        }

    });
AndreasReiff
źródło
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.

Miguel Rdz
źródło
1

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

android:clickable="true"
IgniteCoders
źródło
1

Android: atrybut autoText umożliwia także automatyczne ustawianie ostrości TextView.

Jurij Finczenko
źródło
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.

Samuel Robert
źródło
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.

prashant
źródło
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.

Ted_Zactly
źródło
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

Muhammad Waleed
źródło
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ź !

spcarlin
źródło
-1

Rozwiązałem problem, usuwając klikalne widoki z listy.

sidKhalid
źródło