ListView setOnItemClickListener não funciona ao adicionar o botão

89

Eu tenho uma exibição de lista com texto e botão em cada linha, exibição de lista setOnItemClickListener () não está funcionando. é possível lidar com eventos de clique de item e clique de botão de maneira diferente (o clique do item deve chamar ActivityA e o clique do botão deve chamar ActivityB). Alguém tem uma solução

    private ArrayList<String> userIDArr = null;
    private ArrayList<String> userNameArr = null;
    private DatabaseHelper dbHelper = null;
    private ListView userListView=null; 


    public void onCreate(Bundle savedInstanceState) 
        {
          super.onCreate(savedInstanceState);         
          setContentView(R.layout.list_view);         
          dbHelper = new DatabaseHelper(this.getApplicationContext());        
          Map<String,ArrayList<String>> displayMap = dbHelper.getUserListToDisplay();
          userIDArr = displayMap.get("UserID");
          userNameArr = displayMap.get("FirstName1");           


          userListView = (ListView) findViewById(R.id.listView2);
          userListView.setAdapter(new UserListAdapter(this,userIDArr));


          userListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
              @Override
              public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {

                  Toast.makeText(usersListActivity.this,
                            "Item in position " + position + " clicked", Toast.LENGTH_LONG).show();
              }
            });
     }


    public class UserListAdapter extends ArrayAdapter<String>
    {
        Activity context;
        public UserListAdapter(Activity context, ArrayList<String> names) {
            super(context, R.layout.list_item, names);
            this.context = context;
        }
        private class ViewHolder {
            public TextView UserNameAndID;
            public TextView Description;
            public Button  UploadBtn;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            View rowView = convertView;
            if (rowView == null) {
                LayoutInflater inflater = context.getLayoutInflater();
                rowView = inflater.inflate(R.layout.list_item, null, true);
                holder = new ViewHolder();
                holder.UserNameAndID = (TextView) rowView.findViewById(R.id.User_detailsTxt);
                holder.Description = (TextView) rowView.findViewById(R.id.User_status);
                holder.UploadBtn = (Button) rowView.findViewById(R.id.uploadbutton);
                holder.UploadBtn.setOnClickListener(new View.OnClickListener() {  

                        public void onClick(View v) {  
                        Toast.makeText(usersListActivity.this," Button clicked",Toast.LENGTH_SHORT).show();
                        }   
                    }); 
                    rowView.setTag(holder);
            } else {
                holder = (ViewHolder) rowView.getTag();
            }
            String s = userNameArr.get(position)+","+userIDArr.get(position);
            holder.UserNameAndID.setText(s);
            holder.Description.setText("U r in middle");
            return rowView;
        }
    }
}`
Kishore
fonte

Respostas:

260

Tente definir seus botões (ou qualquer outra visualização que você deseja manipular, clique dentro de um item da lista) assim:

android:focusable="false"
android:focusableInTouchMode="false"
Ben Lee
fonte
@Ben Lee: Eu adicionei isso às minhas caixas de seleção! Ainda não funciona. O que posso estar fazendo de errado?
TDaver
1
android:focusableInTouchMode="false"resolve o meu. Eu uso dois TextView em uma linha LinearLayout personalizada. Yuk android ...
Youngjae,
12
ImageButton não funcionará. Na exibição de item de lista contém ImageButton, defina android: descendantFocusability = "blocksDescendants".
ChangUZ
8
adicionar android: clickable = "false" também pode ser necessário (ative e desative-o no designer de layout para adicioná-lo explicitamente ao XML)
jrg
11
Aviso: Caso você esteja usando um ImageButton, você precisa usar setFocusable (false) porque o construtor de ImageButton habilitaria este atributo após inflar do arquivo xml. Mas boa resposta
Mateu
118

Às vezes, a lista ainda não será capaz de fazer o Click Listener passar. E, neste caso, você pode ter que adicionar mais um atributo.

android:descendantFocusability="blocksDescendants" 

E esse atributo deve ser adicionado ao layout superior de seu XML, onde você forneceu os elementos ListView.

Andro Selva
fonte
Assim, ninguém mais faz o que eu acabei de fazer: isso será indesejável se você tiver algo que requer foco em sua linha, como um EditText. Eu me sinto estúpido agora.
Kitalda
No meu caso, esse conselho ajudou. Tenho um TextView e um RadioButton, o 1º não clicou, o 2º não selecionou o TextView. Escrevi "android: clickable =" false "" no RadioButton.
CoolMind
Esta é a solução quando o botão é um ImageButton
Mahonster
15

Se você tiver uma visão ativa / visão focalizável em sua visão de lista, então ela será desativada onItemClickListener... você pode tentar torná-la não focável adicionando: android:focusable="false"a qualquer visão que normalmente é focalizável.

nilesh
fonte
8

A coisa da massa é adicionar tanto Listenerao todo rowViewquanto ao Buttoninterior Adapter. Algo assim.

public class MyAdapter extends BaseAdapter implements View.OnClickListener{

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
            View rowView = convertView;
            if(rowView == null)
            {
                    //intialize rowView, and set onclick listener only once.
                    rowView = someIntilizationMehhodOrInflatorMethod();
                    //add listener to the button also and also to the row view
                    rowView.setOnClickListener(this);
            }
            //all your inflation and setting values goes here and at the end,
            //set position as tag to get the correct position, rather buggy one.
            rowView.setTag(String.valueOf(position));


            return rowView;
    }
    public void onClick(View v)
    {
            //now get the tag of View v and convert it to integer.
            int pos = Integer.parseInt(v.getTag().toString());
            Toast.makeText(context,"Item in position " + pos + " clicked",Toast.LENGTH_LONG).show();
    }
}
Adil Soomro
fonte
3
Como isso é ainda remotamente melhor? Você está criando um onClickListener para CADA elemento de dados contra apenas 1 ouvinte. Seu exemplo nem mesmo recicla quais visualizações.
JRomero de
@ J.Romero este foi apenas um exemplo, embora haja muito espaço para otimização de código. No entanto, acabei de atualizar o código.
Adil Soomro de
5

Tente definir setClickable(false)para cada Button, ImageButtonetc, e Viewassim:

view.setClickable(false);
button.setClickable(false);
imagebutton.setClickable(false);

Além disso, você tem que adicionar

android:descendantFocusability="blocksDescendants"

para o layout principal (primeiro nível)

Vlad
fonte
2
Eu encontrei conjunto blocksDescendants é suficiente, não há necessidade de cancelar focalizável etc. Android 4.1
djdance
2

Em vez de adicionar o botão, adicione ImageViewe forneça um setOnItemClcikouvinte que funcionaria bem.

public View getView(final int position, View convertView, ViewGroup parent) {
     MyViewHolder mViewHolder;
     if(convertView == null) {
         convertView = inflater.inflate(R.layout.youtubesearchrow, null);
         mViewHolder = new MyViewHolder();
         mViewHolder.alarm = (ImageView)convertView.findViewById(R.id.alarm);
         convertView.setTag(mViewHolder);
     } else {
         mViewHolder = (MyViewHolder) convertView.getTag();
     }

     mViewHolder.tvTitle = detail(convertView, R.id.tvTitle,    
     // mViewHolder.tvDesc  = detail(convertView, R.id.tvDesc,  
     mViewHolder.ivIcon  = detail_image(convertView, R.id.ivIcon,  

     mViewHolder.alarm.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
        // TODO Auto-generated method stub
        }
    });

        return convertView;
}
Sharath Yadhav
fonte
1

Também estou recebendo o mesmo erro. Se no layout da lista você tiver qualquer botão para substituí-lo por TextViewie ImageButtonpor ImageView. Para referência, é o meu código:

private Activity activity;
private LayoutInflater inflater;

private List<ItemList> itemListsItems;

private Bookmark_SharedPref pref;

ImageLoader imageLoader = AppController.getInstance().getImageLoader();

public CustomListAdapter_Item(Activity activity,List<ItemList> itemListsItems){
    this.activity=activity;
    this.itemListsItems=itemListsItems;
    pref = new Bookmark_SharedPref(activity);
}


@Override
public int getCount() {
    return itemListsItems.size();
}

@Override
public Object getItem(int position) {
    return itemListsItems.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

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

    View v = convertView;
    ViewHolder holder;

    if(inflater == null){
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    if(convertView == null){
        convertView = inflater.inflate(R.layout.item_layout,null);

        holder = new ViewHolder();
        convertView.setTag(holder);
    }
    else{
        holder = (ViewHolder)convertView.getTag();
    }


    if(imageLoader == null){
        imageLoader = AppController.getInstance().getImageLoader();
    }




     holder.img = (NetworkImageView)convertView.findViewById(R.id.item_image);
    holder.Title = (TextView)convertView.findViewById(R.id.item_title);
    holder.Cat = (TextView)convertView.findViewById(R.id.item_category);

    holder.id = (TextView)convertView.findViewById(R.id.itemid);

    holder.Desc = (TextView)convertView.findViewById(R.id.item_description);

    holder.book = (ImageView)convertView.findViewById(R.id.bookmark_star);



    // getting blog data or the row
    ItemList il = itemListsItems.get(position);

    //setting image
    holder.img.setImageUrl(il.getImageUrl(), imageLoader);

    // setting title
    holder.Title.setText(il.getTitle());

    //setting category
    holder.Cat.setText(il.getCategory());


    //setting blog id
    holder.id.setText(il.getId());

    //setting description
    holder.Desc.setText(il.getDescription());

    //bookmarking the post
    holder.book.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            itemListsItems.get(position).isFav = !itemListsItems.get(position).isFav;
            ((ImageView)v.findViewById(R.id.bookmark_star)).setImageResource(itemListsItems.get(position).isFav ? R.mipmap.active_star : R.mipmap.inactive_star);

            if(itemListsItems.get(position).isFav){
                String data = Integer.toString(itemListsItems.get(position).id);
                Toast.makeText(v.getContext(),"fav hai "+data,Toast.LENGTH_SHORT).show();
                pref.addPref(data);
            } else {
                String data = Integer.toString(itemListsItems.get(position).id);
                Toast.makeText(v.getContext(),"not fav"+ data,Toast.LENGTH_SHORT).show();
                pref.removePref(data);
            }
            //notifyDataSetChanged();
        }
    });

    ((ImageView)convertView.findViewById(R.id.bookmark_star)).setImageResource(itemListsItems.get(position).isFav ? R.mipmap.active_star : R.mipmap.inactive_star);

    /*
    if(itemListsItems.get(position).isFav){
        String data = Integer.toString(itemListsItems.get(position).id);
        Toast.makeText(convertView.getContext(),"fav hai "+data,Toast.LENGTH_SHORT).show();
        pref.addPref(data);
    } else {
        String data = Integer.toString(itemListsItems.get(position).id);
        //Toast.makeText(convertView.getContext(),"not fav"+ data,Toast.LENGTH_SHORT).show();
        pref.removePref(data);
    }
    */
    return convertView;
}

private static class ViewHolder {
   public TextView Title, Desc,Cat,id;
    ImageView book;
    NetworkImageView img;
}

Lembre-se também de fazer o layout da lista como android:focussable="true"e para aquele botão / parâmetro de texto usado android:focussable="false".

Mukul Aggarwal
fonte
corrigido , deveria ser android: focusable = "false" not focussable
Kenny Dabiri
1

Adicionar android:focusable="false"atributo ao botão e à visão pai adicionar android:descendantFocusability="blocksDescendants"atributo como este.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:descendantFocusability="blocksDescendants">

    <ImageButton
        android:id="@+id/sell_button"
        android:layout_width="wrap_content"
        android:focusable="false"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_sell" />
</RelativeLayout>
Süheyl Kawsara
fonte
0

É incrível notar que como o XML mudou faz com que o setonitemclicked em java funcionou para mim.

android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false"
Waseem Minhas
fonte
0

Faça com que o atributo pai clicável seja falso como este android:clickable="false".

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="false"
    android:orientation="vertical">

Novamente enfrentando o problema, então, para todas as visualizações filhas, adicione este falso clicável.

REMITH
fonte
0

Não sei exatamente por que, mas às vezes quando você configura o adaptador, os ouvintes são limpos. Então, você deve ligar setOnClickListenerdepois de setAdapterou setListAdapter.

Tiago Gouvêa
fonte
0

Remova android:clickable="true"da vista interna do cliente ListView.

Hamid Jolany
fonte