OnListItemClick de ListActivity no funciona

En mi aplicación con ListActivity el sobrescrito onListItemClick la devolución de llamada no se activa al hacer clic en un ListView ít.

He definido una vista de lista personalizada con los siguientes archivos xml, allowinview.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="fill_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_Apply"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btn_apply"
            android:onClick="onApplyClick" />

        <Button
            android:id="@+id/btn_install"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/btn_install"
            android:onClick="onInstallClick" />

        <Button
            android:id="@+id/btn_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel" />

    </LinearLayout>

    <ListView android:id="@android:id/list" 
            android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false">

    </ListView>  
</LinearLayout>

y el diseño del elemento de vista checkable.xml :

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >


   <ImageView android:id="@+id/img" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" android:layout_alignParentBottom="true"
        android:src="@drawable/ic_launcher" android:focusable="false" />

    <CheckBox
        android:id="@+id/check"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       android:layout_alignParentRight="true"
        android:layout_marginLeft="4px"
    android:layout_marginRight="10px"

    android:clickable="true">

 </CheckBox>

    <TextView
        android:id="@+id/label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/img"
        android:gravity="bottom"
        android:text="@+id/label"
        android:textSize="15px"/>
</RelativeLayout>

El definido ArrayAdapter se define como sigue:

     public class InteractiveArrayAdapter extends ArrayAdapter<Model> {


    private final List<Model> list;
    private final Activity context;
    private boolean changeable;

    public InteractiveArrayAdapter(Activity context, List<Model> list, boolean changeable) {
        super(context, R.layout.checkable, list);
        this.context = context;
        this.list = list;
        this.changeable = changeable;
    }

    static class ViewHolder {
        protected TextView text;
        protected CheckBox checkbox;
        protected ImageView image;
        protected int pos;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        if (convertView == null) {
            LayoutInflater inflater = context.getLayoutInflater();
                view = inflater.inflate(R.layout.checkable, null);


            final ViewHolder viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.label);
            viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
            viewHolder.image = (ImageView) view.findViewById(R.id.img);
            viewHolder.pos = position;


            view.setClickable(true);

            if (!changeable)viewHolder.checkbox.setEnabled(false);


            viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {



                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    Model element = (Model) viewHolder.checkbox.getTag();

                    element.setActive(buttonView.isChecked());
                }

            }
            );



            view.setTag(viewHolder);
            viewHolder.checkbox.setTag(list.get(position));

        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));

        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).showPermission());
        holder.checkbox.setChecked(list.get(position).isActive());

        if (list.get(position).isRedundant()) {
            holder.image.setImageDrawable(context.getResources().getDrawable(R.drawable.warning));
        } else {
            holder.image.setImageDrawable(context.getResources().getDrawable(R.drawable.ok));
        }
        return view;

    }

}

En la clase que extiende ListActivity, un ArrayAdapter definido se llena con un arrayList en un asyncTask (la información de la lista se calcula en doInBackground() método):

public class PermissionViewActivity extends ListActivity {

    private final static String TAG = "PMA";
    ...
     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.permissionview);
        ...
    }

    ... 

     private class CurrentPermissions extends AsyncTask<String, Integer, String> {

        private ListActivity la;
        private Context context;



        private int progress = 0;

        public CurrentPermissions(ListActivity la) {
            this.la = la;
            this.context = la;

        }

        protected void onPreExecute() {
        ...

        protected void onPostExecute(String result) {
          adapter = new InteractiveArrayAdapter(la, permissionList, changeable);
          la.setListAdapter(adapter);
          /output with number of listitems
              System.out.println("DEBUG1 " + la.getListAdapter().getCount());
        }
     }
      ...
      @Override
      protected void onListItemClick(ListView l,  View view, int position, long id) {
        super.onListItemClick(l, view, position, id);
        System.out.println("clicked !");
      }
      ...
    }

La onListItemClick el método no se ejecuta. Al definir onClickListener en ArrayAdapter, el evento de clic funciona:

 view.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {

                    System.out.println("Klick D1 " + list.get(viewHolder.pos));

                }

            });

¿Por qué funciona la definición del evento de clic en ArrayAdapter, pero no sobrescribir en ListActivity? no encuentro el fallo

preguntado el 22 de mayo de 12 a las 21:05

4 Respuestas

Intente también configurar el CheckBox del diseño de la fila como no focusable:

//...
 <CheckBox
    android:id="@+id/check"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_marginLeft="4px"
    android:layout_marginRight="10px"
    android:focusable="false" 
    android:clickable="true">

//...

contestado el 22 de mayo de 12 a las 21:05

Lea acerca de los problemas enfocables y probé esto, pero no ayudó. - user1411093

@ user1411093 ¿También has probado el android:descendantFocusability="beforeDescendants" propiedad en su ListView(y quitar el android:focusable="false" from the ListView)?(pero mantén el android:focusable="false" al CheckBox) - usuario

Finalmente encontré la solución, era android:descendantFocusability="afterDescendants" Gracias por su ayuda. - user1411093

Si desea tener un oyente de clics "general" (aplicable a todos los elementos en su vista de lista), su actividad debe implementar OnItemClickListener

public class PermissionViewActivity extends ListActivity implements OnItemClickListener

Se le pedirá que anule el método

@Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3)
{
     Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show();
}

Luego debe configurar manualmente el oyente de clics en su vista de lista

ex.

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.permissionview);
        ...
        getListView().setOnItemClickListener(this);
}

contestado el 22 de mayo de 12 a las 21:05

Intenté esto, pero no funcionó. los getListView() entrega un objeto, también puede acceder a él con getOnItemClickListener pero el oyente no "disparó" cuando hice clic. No puedo encontrar el problema, ¿hay alguna opción que pueda evitar la ejecución de un evento de escucha? - user1411093

¡Sí! Tiene una casilla de verificación en su vista de lista que esencialmente "robará" la funcionalidad de clic de la vista de lista. bajo tu etiqueta en su checkable.xml agregue android:focusable="false" - dymmeh

Sí, lo descubrí, los checkbos "roban" el evento de clic, cuando configuro clickable="false"para la casilla de verificación, el elemento de lista de clic vor funciona, pero necesito ambos y el enfocable no funciona. - user1411093

Finalmente encontré la solución, era android:descendantFocusability="afterDescendants" Gracias por su ayuda. - user1411093

Hago esto en mi vista que contiene el ListView por:

ListView lv = (ListView)findViewById(R.id.myList);
lv.setAdapter(new myCustomAdapter,items);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){
    public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id){
        /* do something i've been clicked */

});

o aquí en un evento onItemSelected

lv.setOnItemSelectedListener(new AdapterView.onItemSelectedListener(){
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id){
        ...
    }
    public void onNothingSelected(AdapterView<?> arg0){
        ...
    }
});

Espero que esto ayude

contestado el 22 de mayo de 12 a las 21:05

Intenté un enfoque similar pero definí ListView lv = getListView(). no entiendo donde esta el id myListse define ? Un ListView de pensamiento debe definirse con @android:id/list ? - user1411093

Si tiene vistas en las que se puede hacer clic dentro de ListItem, el indicador enfocable debe establecerse en falso. Al configurar focusable=false en el diseño, se sobrescribirá cuando el Listener se configure programáticamente.

Mi solución funcionó para mí invocando programáticamente establecer la capacidad de enfoque

listview.setOnItemClickListener(this);
listview.setFocusable(false);

Respondido el 11 de Septiembre de 14 a las 12:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.