ListView setOnItemClickListener non funziona aggiungendo il pulsante


89

Ho una visualizzazione elenco con testo e pulsante in ogni riga, la visualizzazione elenco setOnItemClickListener () non funziona. è possibile gestire gli eventi di clic sull'elemento e clic sul pulsante in modo diverso (il clic sull'elemento dovrebbe chiamare ActivityA e il clic sul pulsante dovrebbe chiamare ActivityB). Qualcuno ha una soluzione

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

Risposte:


260

Prova a impostare i pulsanti (o qualsiasi altra visualizzazione che desideri gestire facendo clic all'interno di un elemento dell'elenco) in questo modo:

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

@ Ben Lee: li ho aggiunti alle mie caselle di controllo! Continua a non funzionare. Cosa posso fare di sbagliato?
TDaver

1
android:focusableInTouchMode="false"risolve il mio. Uso due TextView in una riga LinearLayout personalizzata. Yuk android ...
Youngjae

12
ImageButton non funzionerà. Nella visualizzazione dell'elemento elenco contiene ImageButton, impostare android: descendantFocusability = "blocksDescendants".
ChangUZ

8
può anche essere richiesta l'aggiunta di android: clickable = "false" (attivala e disattivala nel designer del layout per aggiungerla esplicitamente all'XML)
jrg

11
Avvertenza: nel caso in cui si utilizzi un ImageButton è necessario utilizzare setFocusable (false) perché il costruttore di ImageButton abiliterebbe questo attributo dopo l'inflazione dal file xml. Ma buona risposta però
Mateu

118

A volte l'elenco non sarà ancora in grado di far passare il listener di clic. E in questo caso potresti dover aggiungere un altro attributo.

android:descendantFocusability="blocksDescendants" 

E questo attributo deve essere aggiunto al layout più in alto del tuo XML in cui hai fornito gli elementi ListView.


Solo così nessun altro fa quello che ho appena fatto: questo non sarà desiderabile se hai qualcosa che richiede focus nella tua riga come un EditText. Mi sento stupido adesso.
Kitalda

Nel mio caso questo consiglio ha aiutato. Ho un TextView e RadioButton, il primo non aveva cliccato, il secondo non aveva selezionato TextView. Ho scritto "android: clickable =" false "" in RadioButton.
CoolMind

Questa è la soluzione quando il pulsante è un ImageButton
Mahonster

15

Se hai una vista attiva / vista attivabile nella tua visualizzazione elenco, questa verrà disattivata onItemClickListener... puoi provare a renderla sfocabile aggiungendo: android:focusable="false"a qualsiasi visualizzazione normalmente attivabile.


8

La cosa della pastella è aggiungere sia Listeneral tutto rowViewche al Buttondentro Adapter. Qualcosa come questo.

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

3
Come è anche lontanamente migliore? Stai creando un onClickListener per OGNI elemento di dati rispetto a 1 solo ascoltatore. Il tuo esempio non ricicla nemmeno le visualizzazioni.
JRomero

@ J.Romero questo era solo un esempio, anche se c'è molto spazio per l'ottimizzazione del codice. Tuttavia ho appena aggiornato il codice.
Adil Soomro

5

Provare set setClickable(false)per ciascuna Button, ImageButtonecc e Viewin questo modo:

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

Inoltre devi aggiungere

android:descendantFocusability="blocksDescendants"

al layout principale (primo livello)


2
Ho trovato blocchi impostati Discendenti è sufficiente, non è necessario annullare il focusable ecc. Android 4.1
djdance

2

Invece di aggiungere il pulsante aggiungi ImageViewe fornisci un setOnItemClciklistener che funzionerebbe bene.

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

1

Ricevo anche lo stesso errore. Se nel layout della lista hai un pulsante per sostituirlo con TextViewie ImageButtoncon ImageView. Per riferimento il loro è il mio codice:

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

Inoltre, tieni presente di rendere il layout della lista come android:focussable="true"e per quel pulsante / parametro di testo android:focussable="false".


corretto dovrebbe essere Android: focusable = "false" non focalizzabile
Kenny Dabiri,

1

Aggiungi android:focusable="false"attributo al pulsante e alla vista padre aggiungi un android:descendantFocusability="blocksDescendants"attributo in questo modo.

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

0

È sorprendente notare che il modo in cui XML è cambiato fa sì che setonitemclicked in java abbia funzionato per me ..

android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false"

0

Rendi l'attributo selezionabile principale su false in questo modo 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">

Di nuovo affrontando il problema, quindi per tutte le visualizzazioni figlio aggiungi questo falso cliccabile.


0

Non so esattamente perché, ma a volte quando si imposta l'adattatore, gli ascoltatori vengono cancellati. Quindi, devi chiamare setOnClickListenerdopo setAdaptero setListAdapter.


0

Rimuovere android:clickable="true"dalla vista interna del cliente dal file ListView.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.