OnItemCLickListener não está funcionando na exibição de lista


242

Activity código da classe:

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");
    }
});

A getViewfunção na Adapterclasse:

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);
    }
}

Existe um problema com o uso de dois xmls ao inflar?


4
@ hiei Meu problema era que eu estava usando botões de imagem em minhas células de layout. Mesmo depois de adicionar "android: descendantFocusability", meu ouvinte de cliques não estava respondendo. O que fiz foi alterar todos os ImaegButtons para ImageViews. Isso resolveu meu problema.
Ajith Memana

Respostas:


730

Acabei de encontrar uma solução a partir daqui, mas com um clique profundo.

Se qualquer item de linha da lista contiver uma exibição focável ou clicável, OnItemClickListenernão funcionará.

O item de linha deve ter um parâmetro semelhante android:descendantFocusability = "blocksDescendants".

Aqui você pode ver um exemplo de como deve ser o item da sua lista. O item da lista xml deve ser ... 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>

não funciona para mim. Alguém pode dar uma olhada em [ stackoverflow.com/questions/21692209/… #
suitianshi

3
Você também pode definir isso de forma programática com listView.setDescendantFocusability(int focus);onde focusestá um dos ViewGroup.FOCUS_BEFORE_DESCENDANTS, ViewGroup.FOCUS_AFTER_DESCENDANTSouViewGroup.FOCUS_BLOCK_DESCENDANTS
Max Worg

Acho engraçado que 20 pessoas tenham te agradecido em um comentário. Estou com esse problema há 8 horas, muito obrigado por isso.
Sparticvs

1
Minha pergunta é: este é um bug do Android ou é por design?
Fangzhzh 19/10/2015

Estou preso há 6 horas e preciso muito de ajuda. stackoverflow.com/questions/35108940/why-cant-i-remove-an-item/...
Ruchir Baronia

89

O problema é que seus layouts contêm itens focáveis ​​ou clicáveis. Se uma exibição contiver itens focáveis ​​ou clicáveis, o OnItemCLickListener não será chamado.

Clique aqui para mais informações.

Poste um dos seus xmls de layout, se esse não for o caso.


2
Esta foi a solução para mim, eu estava declarando minha visão como clicável. Obrigado!
kingraam

1
Obrigado! Alterei meus 2 EditTexts para TextViews, e ele CheckBoxfoi autorizado a permanecer (e permanecer alternável) com android:descendantFocusability="blocksDescendants"adicionado ao meu LinearLayout.
Azurespot

Sim! Eu tinha android:focusableInTouchMode="true"para a linha, uma vez removido, começou a trabalhar, finalmente! :-)
SharpC

58

Para minhas listas, minhas linhas têm outras coisas que podem ser clicadas, como botões, para fazer um cobertor blocksDescendantsnão funcionar. Em vez disso, adicionei uma linha no xml do botão:

android:focusable="false"

Isso evita que os botões bloqueiem os cliques nas linhas, mas ainda permite que os botões recebam os cliques.


@ user1840899 Esta é uma resposta comum e que aprendi, por isso a passei. É uma informação correta, não digna de voto negativo.
Janene Pappas

Isso funciona para mim em uma caixa de seleção itens ListView (sem blocksDescendants)
thpitsch

Isso corrige o bug, mantendo os botões (ToggleButton para mim) clickable
Mohsen Afshin

A única maneira de obter um GridView com RadioButtons funcionando era aplicar o android: descendantFocusability = "blocksDescendants" no LinearLayout que contém o RadioButton e definindo android: clickable = "false" no próprio RadioButton.
Stephen McCormick

Estou preso há 6 horas e preciso muito de ajuda. stackoverflow.com/questions/35108940/why-cant-i-remove-an-item/...
Ruchir Baronia

34

você precisa executar 2 etapas em seu listview_item.xml

  1. defina o layout raiz com: android:descendantFocusability="blocksDescendants"
  2. defina qualquer visualização focável ou clicável neste item com:
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="false"

Aqui está um exemplo: 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>

A configuração clickable="truena exibição do item fará com que o onItemClicknão seja chamado. Portanto, preste atenção para adicionar também clickable="false"na visualização raiz do item, neste caso, é oLinearLayout
vovahost 15/02/16

Definir android: descendantFocusability = "blocksDescendants" me ajuda. Obrigado!
precisa saber é o seguinte

21/12/16, e após horas de pesquisa, ISTO funcionou, obrigado, cara!
Tanner Summers

Se você tiver o mesmo layout que paisagem, etc., faça-o também.
Immy

19

use o código abaixo na tag do botão no layout de linha personalizado do listview

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

Grande homem foi realmente útil !!
divyansh ingle

isso funcionou aqui !! Eu tenho muitos checkbox nesta vista e eu tento com android:descendantFocusability="blocksDescendants"e bloquear estes caixa de seleção clique
Armando Marques Sobrinho

17

Eu tive o mesmo problema e acabei de ver que havia definido acidentalmente:

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

na minha classe CustomListViewAdapter.

Alterando isso para:

return true;

Eu consegui resolver o problema. Caso alguém tenha cometido o mesmo erro ...


7
Eu também tive um@Override public void onApplicationStart { ExplodeThisDevice(); }
Léon Pelletier

17

Usar android: descendente

<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" >

Adicionar acima no layout raiz


2
A adição de detalhes pode tornar essa uma resposta melhor e marcar com +1.
assassino

Isso funcionou para mim e meu botão no elemento list ainda funcionou como pretendido.
Gustav Eriksson


10

se você tiver visualizações de texto, botões ou stg clicáveis ​​ou selecionáveis ​​apenas na exibição de linha

android:descendantFocusability="blocksDescendants"

não é o suficiente. Você tem que definir

android:textIsSelectable="false"

para suas visualizações de texto e

android:focusable="false"

aos seus botões e outros itens focáveis.


Eu aprendi isso da maneira mais difícil. android: textIsSelectable = "false" Cuidado com isso :)
diyoda_


5

Eu tive o mesmo problema e tentei todas as soluções mencionadas sem sucesso. através de testes, descobri que tornar o texto selecionável estava impedindo que o ouvinte fosse chamado. Então, alternando para false ou removendo, meu ouvinte foi chamado novamente.

android:textIsSelectable="false"

espero que isso ajude alguém que estava preso como eu.


4
  1. Adicione isso no layout principal

    android:descendantFocusability="blocksDescendants"
  2. Escreva esse código em todos os botões, TextView, ImageView etc. que tenham onClick

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

Espero que funcione.


3

Duas soluções impressionantes foram: se o seu ListFragment de extensão de um fragmento souber que mListView.setOnItemClickListenernão será chamado antes da criação da sua atividade, isso garantirá que seja definido quando a atividade for criada

@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);
        }
    });
}

Enquanto olhava para o código-fonte do ListFragment, me deparei com isso

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) {
    }
}

Um onItemClickListenerobjeto é anexado e chama onListItemClick() Como tal, a outra solução semelhante, que funciona exatamente da mesma maneira, é substituironListItemClick()

@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

no meu caso, nenhuma das propriedades de layout xml não foi útil.

Acabei de adicionar uma única linha de código como esta: 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;
}

basicamente, ele faz a mesma coisa que configurar propriedades no layout xml, mas foi a única coisa que funciona no meu caso.

Não é o momento perfeito, mas talvez ajude alguém Feliz codificação


1

Eu tentei tudo o que precede e NADA funcionou.

Resolvi o problema da seguinte maneira:

Primeiro, defino um botão personalizado chamado 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();
    }
}

}

O XML se parece com:

<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"  
/>

Em seguida, defino minha própria ButtonClickedinterface do Ouvinte:

public interface ButtonClickedListener {
    public void ButtonClicked();
}

Então eu uso meu próprio ouvinte como se fosse o normal 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

Eu tive o mesmo problema, estava usando um estilo para meus textos no layout de linha que tinha o atributo "focalizável". Funcionou depois que eu o removi.


1

No meu caso, tive que remover a próxima linha do Layout

android:clickable="true"

1

Android: o atributo autoText também torna o TextView automaticamente focável.


0

Se você deseja usar o clique simples e o clique longo nos itens de exibição em lista, a melhor maneira de implementar isso seria usar o menu de contexto para um clique longo. Evite usar setItemLongClickListener, especialmente se você tiver vários layouts de linha para sua exibição de lista.


0

Enfrentou o mesmo problema, tentou por horas. Se você tentou todas as opções acima, tente alterar layout_width do Listview e item de lista para match_parent de wrap_content.


0

Todas as opções acima falharam para mim. No entanto, consegui resolver o problema (depois de muitas horas batendo na cabeça - Google, se você estiver ouvindo, considere corrigir o que encontrei abaixo na forma de erros do compilador, se possível)

Você realmente precisa ter cuidado com os atributos do Android adicionados ao seu layout xml aqui (nesta pergunta original, isso é chamado de list_items.xml). Para mim, o que estava causando o problema era que eu havia mudado de uma visualização EditText para uma TextView e tinha sobras de atributos da alteração (no meu caso, inputType). O compilador não pegou e a clicabilidade falhou quando fui executar o aplicativo. Verifique todos os atributos que você possui nos nós xml do layout.


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;
}

Em sua atividade, use adapter.setOnItemClickListener () antes de anexá-lo à lista.

Copiado do github funcionou para mim


0

O que funcionou para mim foi adicionar o código abaixo a todas as subvisões dentro do layout do meu arquivo row.xml:

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

Então, no meu caso:

<?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>

E esta é minha chamada setOnItemClickListener na minha subclasse 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
            }

        });

Eu tenho a resposta daqui !


-1

Resolvi o problema removendo as visualizações clicáveis ​​da lista.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.