ListView setOnItemClickListener не работает при добавлении кнопки


92

У меня есть представление списка с текстом и кнопкой в ​​каждой строке, представление списка setOnItemClickListener () не работает. Можно ли по-разному обрабатывать события нажатия элемента и кнопки (нажатие элемента должно вызывать ActivityA, а нажатие кнопки должно вызывать ActivityB). У кого-нибудь есть решение

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

Ответы:


261

Попробуйте настроить свои кнопки (или любые другие представления, которые вы хотите обрабатывать щелчком внутри элемента списка) следующим образом:

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

@Ben Lee: Я добавил это в свои флажки! Все еще не работает. Что я делаю не так?
TDaver

1
android:focusableInTouchMode="false"решает мой. Я использую два TextView в настраиваемой строке LinearLayout. Юк андроид ...
Ёнджэ 09

12
ImageButton работать не будет. В представлении элемента списка, содержащего ImageButton, установите android: DescendantFocusability = "blocksDescendants".
ChangUZ

8
также может потребоваться добавление android: clickable = "false" (включите и выключите его в дизайнере макета, чтобы явно добавить его в XML)
jrg

11
Предупреждение: в случае, если вы используете ImageButton, вам нужно использовать setFocusable (false), потому что конструктор ImageButton включит этот атрибут после расширения из файла xml. Но хороший ответ
Матеу

120

Иногда список по-прежнему не может передать прослушиватель кликов. И в этом случае вам, возможно, придется добавить еще один атрибут.

android:descendantFocusability="blocksDescendants" 

И этот атрибут нужно добавить в самый верхний макет вашего XML, где вы предоставили элементы ListView.


Просто чтобы никто другой не делал того, что я только что сделал: это будет нежелательно, если у вас есть что-то, требующее фокуса в вашей строке, например EditText. Я чувствую себя глупо.
Kitalda

В моем случае этот совет помог. У меня есть TextView и RadioButton, первый не щелкнул, второй не выбрал TextView. Я написал "android: clickable =" false "" в RadioButton.
CoolMind 01

Это решение, когда кнопка представляет собой ImageButton
Mahonster

Любопытно, что это решение сработало для меня. OnItemClickListener работает, не влияя на дочерние события. Не знаю, почему это сработало, так что ... разберись.
ONE

15

Если у вас есть активное представление / представление с фокусировкой в ​​представлении списка, оно отключится onItemClickListener... вы можете попытаться сделать его нефокусируемым, добавив: android:focusable="false"к любому представлению, которое обычно фокусируется.


8

Кляр нужно добавлять как Listenerво все, так rowViewи Buttonвнутрь Adapter. Что-то вроде этого.

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
Как это хоть отдаленно лучше? Вы создаете onClickListener для КАЖДОГО элемента данных, а не только для 1 слушателя. Ваш пример даже не перерабатывает, какие представления.
JRomero

@ J.Romero это был всего лишь пример, хотя для оптимизации кода есть много места. Однако я только что обновил код.
Adil Soomro

5

Попробуйте установить setClickable(false)для каждого Button, ImageButtonи т.д. и Viewвот так:

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

Также вам нужно добавить

android:descendantFocusability="blocksDescendants"

на основной (первый уровень) макет


2
Я обнаружил, что set BlocksDescendants достаточно, нет необходимости отменять фокусировку и т. Д. Android 4.1
djdance

2

Вместо добавления кнопки добавьте ImageViewи предоставьте setOnItemClcikслушателя, который будет работать нормально.

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

Я тоже получаю ту же ошибку. Если в списке макет вы имеете любую кнопку , чтобы заменить его , TextViewт.е. ImageButtonс ImageView. Для справки это мой код:

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

Также не забывайте создавать макет списка так же, как android:focussable="true"и для использования этого параметра кнопки / текста android:focussable="false".


исправлено должно быть android: focusable = "false" not focussable
Кенни Дабири

1

Добавьте android:focusable="false"атрибут к кнопке, а к родительскому представлению добавьте android:descendantFocusability="blocksDescendants"атрибут, подобный этому.

<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

Удивительно заметить, как изменение XML приводит к тому, что setonitemclicked в java Работал для меня ..

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

0

Сделайте родительский атрибут clickable равным false, как это 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">

Опять сталкиваюсь с проблемой, затем для всех дочерних представлений добавьте этот кликабельный false.


0

Я точно не знаю почему, но иногда при установке адаптера слушатели очищаются. Затем вы должны позвонить setOnClickListenerпосле setAdapterили setListAdapter.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.