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?

hiei
fonte
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>
Bhavesh Hirpara
fonte
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.

balazsbalazs
fonte
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.

Janene Pappas
fonte
@ 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>
Eddy
fonte
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"
Milan Shukla
fonte
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 ...

Woody
fonte
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

Amar Gore
fonte
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
11

Eu o resolvi com a ajuda desta resposta

1. Adicione o seguinte no Layout linear de list_items.xml android:descendantFocusability="blocksDescendants"

2.Vistas para crianças do LinearLayout em list_items.xml

 android:focusable="false" 
RAJESH KUMAR ARUMUGAM
fonte
Seu link está quebrado.
Jason C
1
@JasonC Obrigado pela sua informação. Aqui está o link stackoverflow.com/a/14915758/5740760
RAJESH KUMAR ARUMUGAM
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.

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

Mesmo com o mesmo problema, estou com a caixa de seleção, fiz o seguinte para mascarar o itemClickListener,

Adicionadas as seguintes propriedades à caixa de seleção,

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

e ItemClickListner começaram a trabalhar.

Para um exemplo detalhado, você pode acessar o link,

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

Espero que ajude Cheers !!

Gokul Kulkarni
fonte
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.

u2tall
fonte
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.

Wajid khan
fonte
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);
} 
Rowland Mtetezi
fonte
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

Marek Skóra
fonte
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...
        }

    });
AndreasReiff
fonte
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.

Miguel Rdz
fonte
1

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

android:clickable="true"
IgniteCoders
fonte
1

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

Yury Finchenko
fonte
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.

Samuel Robert
fonte
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.

prashant
fonte
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.

Ted_Zactly
fonte
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

Muhammad Waleed
fonte
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 !

spcarlin
fonte
-1

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

sidKhalid
fonte