user2981113 user2981113 - 23 days ago 5
Android Question

How do I add an onclicklistener to a button inside a listview adapter?

I have a listview that contains the list of all my users. Every item from the list is a layout that has a button to show an AlertDialog to change the value of the label of the button. How can I dynamically add an on click event to that button that is generated by the listview Adapter?

This is my adapter:

public class PerfilAdapter extends BaseAdapter {
Context mContext;
LayoutInflater mLayoutInflater;
List<PerfilBean> listaPerfiles = new ArrayList<PerfilBean>();
public Settings01 set=new Settings01();
public PerfilAdapter(Context context,List<PerfilBean> lista) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
listaPerfiles=lista;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return listaPerfiles.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listaPerfiles.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
RelativeLayout itemView;

if (convertView == null) {
itemView = (RelativeLayout) mLayoutInflater.inflate(
R.layout.item_perfil, parent, false);
} else {
itemView = (RelativeLayout) convertView;
}
// obtengo los valores de la vista
Button moneda = (Button) itemView.findViewById(R.id.Moneda);
TextView titulo = (TextView) itemView.findViewById(R.id.Titulo);
TextView nombredesc = (TextView) itemView.findViewById(R.id.txtNombre);
TextView descripcion = (TextView) itemView.findViewById(R.id.txtDescripcion);
String nombreM = Metodos.monedas[listaPerfiles.get(position).getPerfil_tipoMoneda()];
moneda.setText(nombreM);
titulo.setText(listaPerfiles.get(position).getPerfil_nombre());
nombredesc.setText(listaPerfiles.get(position).getPerfil_nombreSec());
descripcion.setText(listaPerfiles.get(position).getPerfil_texto());

return itemView;

}
// metodo parahacer la vista de la celda


public void actualizaDatosLista(List<PerfilBean> listaPerfilesM) {
for(int i=0;i<listaPerfilesM.size();i++){
Log.d("ITEM "+i,listaPerfilesM.get(i).getPerfil_nombreSec());
}
listaPerfiles = listaPerfilesM;
notifyDataSetChanged();
}}


and this is my Activity:

public class Settings01 extends Activity implements OnClickListener {

private List<PerfilBean> lst;
private PerfilDAO perfildao;
private PerfilAdapter perfiladapter;
private ListView lstPerfiles;

public void changeMoneda(final int position) {
int x = 0;

AlertDialog.Builder builder = new AlertDialog.Builder(Settings01.this);
builder.setTitle("Seleccione Tipo de Distribuidor");
builder.setItems(R.array.moneda, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
lst.get(position).setPerfil_tipoMoneda(item);
perfiladapter = new PerfilAdapter(getApplicationContext(), lst);
lstPerfiles.setAdapter(perfiladapter);
dialog.dismiss();
}

});
builder.create();
builder.show();

}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings01);
lstPerfiles = (ListView) findViewById(R.id.lstSettings);
perfildao = new PerfilDAOImplDB(Settings01.this);
lst = new ArrayList<PerfilBean>();
lst = perfildao.getAll();
perfiladapter = new PerfilAdapter(getApplicationContext(), lst);
Log.d("Info", "En Settings");
lstPerfiles.setAdapter(perfiladapter);



}

@Override
public void onClick(View v) {
Log.d("Info", "derp" + v.getId());

}}


This is the layout that my adapter is currently using:

<?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="match_parent" >

<TextView
android:id="@+id/Titulo"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="150dp"
android:gravity="left|center_vertical"
android:textColor="@color/Negro"
android:text="derp" />

<TextView
android:id="@+id/lblTipoMoneda"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_toLeftOf="@+id/Moneda"
android:gravity="left|center_vertical"
android:text="Tipo de moneda: " />

<Button
android:id="@+id/Moneda"
android:layout_width="160dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_marginRight="150dp"
android:gravity="left|center_vertical"
android:background="@color/Blanco"
android:textColor="@color/Negro"
android:text="Peso argentino" />

<ImageView
android:id="@+id/Separador"
android:layout_width="match_parent"
android:layout_height="2.5dp"
android:layout_below="@+id/Moneda"
android:layout_marginLeft="150dp"
android:layout_marginRight="150dp"
android:background="@color/Negro" />

<TextView
android:id="@+id/Nombre"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_below="@+id/Separador"
android:layout_marginLeft="150dp"
android:layout_marginTop="10dp"
android:clickable="true"
android:gravity="left|center_vertical"
android:onClick="changeMoneda"
android:text="Nombre :" />

<EditText
android:id="@+id/txtNombre"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_below="@+id/Separador"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/Nombre"
android:background="@drawable/fondotxt"
android:textColor="@color/Negro"
android:inputType="text" />

<TextView
android:id="@+id/lblTitulo"
android:layout_width="360dp"
android:layout_height="24dp"
android:layout_below="@+id/txtNombre"
android:layout_marginTop="10dp" />

<EditText
android:id="@+id/txtDescripcion"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_below="@+id/lblTitulo"
android:layout_marginLeft="150dp"
android:layout_marginRight="150dp"
android:textColor="@color/Negro"
android:gravity="left|center_vertical" />

<ImageView
android:id="@+id/imgPicturefantes"
android:layout_width="100dp"
android:layout_height="150dp"
android:layout_below="@+id/txtDescripcion"
android:layout_toLeftOf="@+id/lblFotoAntes"
android:src="@drawable/what" />

<ImageView
android:id="@+id/imgPicturefdespues"
android:layout_width="100dp"
android:layout_height="150dp"
android:layout_below="@+id/txtDescripcion"
android:layout_marginLeft="50dp"
android:layout_toRightOf="@+id/centerPoint"
android:src="@drawable/what" />

<TextView
android:id="@+id/lblFotoDespues"
android:layout_width="120dp"
android:layout_height="50dp"
android:layout_below="@+id/txtDescripcion"
android:layout_marginTop="50dp"
android:layout_toRightOf="@+id/imgPicturefdespues"
android:gravity="center"
android:text="Foto despues: "
android:textSize="18sp" />

<ImageButton
android:id="@+id/btnDespuesF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/btnAntesF"
android:layout_toRightOf="@+id/imgPicturefdespues"
android:background="@drawable/btnupload" />

<TextView
android:id="@+id/centerPoint"
android:layout_width="2dp"
android:layout_height="2dp"
android:layout_below="@+id/txtDescripcion"
android:layout_centerHorizontal="true" />

<TextView
android:id="@+id/lblFotoAntes"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_below="@+id/txtDescripcion"
android:layout_marginRight="50dp"
android:layout_marginTop="50dp"
android:layout_toLeftOf="@+id/centerPoint"
android:gravity="center"
android:text="Foto antes: "
android:textSize="18sp" />

<ImageButton
android:id="@+id/btnAntesF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/lblFotoAntes"
android:layout_marginRight="75dp"
android:layout_toLeftOf="@+id/centerPoint"
android:background="@drawable/btnupload" />



Answer

You can do so in the getView() method of your adapter. For that you will need to use a custom adapter (if you are not doing that already). It will be better if you can show the relevant portions of your code.

EDIT: The dialog will be shown by your activity. So you can create an interface for listening to this button click event.

public interface BtnClickListener {
    public abstract void onBtnClick(int position);
}

Let your custom adapter receive it as input.

private BtnClickListener mClickListener = null;
public PerfilAdapter(Context context, List<PerfilBean> lista, BtnClickListener listener) {
    mContext = context;
    mLayoutInflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    listaPerfiles=lista;
    mClickListener = listener;
}

Now you can simply set the normal onClickListener in getView() as below

Button moneda = (Button) itemView.findViewById(R.id.Moneda);
moneda.setTag(position); //For passing the list item index
moneda.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(mClickListener != null)
            mClickListener.onBtnClick((Integer) v.getTag());                
    }
});

Let your activity pass the required BtnClickListener as part of adapter creation.

perfiladapter = new PerfilAdapter(getApplicationContext(), lst, new BtnClickListener() {

    @Override
    public void onBtnClick(int position) {
        // TODO Auto-generated method stub
        // Call your function which creates and shows the dialog here
        changeMoneda(position);
    }

});

Assuming that lst.get(position).setPerfil_tipoMoneda(item); changes the text which will be used as button text correctly, you should simply call perfiladapter.notifyDataSetChanged() in the onClick of your dialog (Currently you are creating the adapter again which is not required).

public void onClick(DialogInterface dialog, int item) {
    lst.get(position).setPerfil_tipoMoneda(item);
    perfiladapter.notifyDataSetChanged();
    dialog.dismiss();
}

Hope it will work as you expect it to.