android listview radio-button listviewitem

Android ListView con RadioButton en el modo singleChoice y un diseño de fila personalizado



radio-button listviewitem (7)

Acabo de tener un problema similar. Parecía que estaba relacionado con el reciclaje de vistas. Pero agregué Log en todas partes y noté que el manejo del reciclaje estaba bien. El problema era el manejo de RadioButtons. Estaba usando:

if(answer == DBAdapter.YES){ rbYes.setChecked(true); rbNo.setChecked(false); } else if(answer == DBAdapter.NO){ rbYes.setChecked(false); rbNo.setChecked(true); } else{ rbYes.setChecked(false); rbNo.setChecked(false); }

y la forma correcta de hacerlo es:

if(answer == DBAdapter.YES){ rbYes.setChecked(true); } else if(answer == DBAdapter.NO){ rbNo.setChecked(true); } else{ RadioGroup rg = (RadioGroup)(holder.answerView); rg.clearCheck(); }

Tengo un ListView , que está en modo singleChoice . Todo lo que quiero es mostrar un RadioButton a un costado, que cuando se hace clic en resalta para decir que está seleccionado, y cuando se hace clic en uno diferente, uno vuelve a ser no seleccionado y el nuevo se selecciona. ¿Por qué es tan difícil? Esto no debería ser tan complicado. He pasado DÍAS buscando una respuesta adecuada a esto y no he encontrado nada, por lo que estoy preguntando con esperanza de una manera clara y concisa.

Mi diseño para la vista de lista (R.layout.view_orders) :

<?xml version="1.0" encoding="utf-8"?> <ListView android:choiceMode="singleChoice" android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/list_divider" android:dividerHeight="1px" android:focusable="false" android:focusableInTouchMode="false" android:cacheColorHint="#00000000"> </ListView>

Mi fila personalizada (R.layout.orders_row) :

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:app="http://schemas.android.com/apk/res/com.xxx.xxxxxx" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="6dip"> <com.xxx.xxxxxx.VerticalLabelView app:text="SHORT" app:textColor="#666" app:textSize="14sp" android:id="@+id/state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" /> <TextView android:id="@+id/quantity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/state" android:layout_centerVertical="true" android:gravity="center" android:textSize="40sp" android:layout_margin="2dip" android:minWidth="30dip" android:textColor="#555" /> <RelativeLayout android:layout_toRightOf="@id/quantity" android:layout_centerVertical="true" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/instrument" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="#333" android:layout_marginLeft="2dip" android:layout_marginRight="2dip" /> <TextView android:id="@+id/deets" android:layout_below="@id/instrument" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="#888" android:layout_marginLeft="2dip" android:layout_marginRight="2dip" /> </RelativeLayout> <RadioButton android:id="@+id/selector" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> </RelativeLayout>

Mi método onCreate () :

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_orders); client = new Client(handler); ola = new OrdersAdapter(this, R.layout.orders_row, Orders); setListAdapter(ola); final RelativeLayout loading = (RelativeLayout) findViewById(R.id.loading); panel = (PositionsPanel) findViewById(R.id.panel); Utility.showProgressBar(loading); client.Connect("orders"); }

Ahora todo lo que subyace funciona de la manera esperada, haz clic en un botón de radio y, a través de su etiqueta, puedo seleccionar ese elemento de la lista y manipularlo como yo quiera. Sin embargo, cuando se hace clic en el primer botón de opción, se seleccionará el último. Haga clic en el mismo botón de radio nuevamente, y ahora también está seleccionado. Haga clic una vez más y no pasa nada, tanto el último como el primero están seleccionados. Ahora hago clic en cualquier otro en la lista, se selecciona como se esperaba. Haga clic en cualquiera de los botones de opción seleccionados y no ocurre nada, el botón de opción permanece seleccionado.

He intentado usar lo siguiente en onCreate () :

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_orders); client = new Client(handler); ola = new OrdersAdapter(this, android.R.layout.simple_list_item_single_choice, Orders); setListAdapter(ola); final RelativeLayout loading = (RelativeLayout) findViewById(R.id.loading); panel = (PositionsPanel) findViewById(R.id.panel); Utility.showProgressBar(loading); client.Connect("orders"); }

y eso simplemente no muestra botones de radio en absoluto. IMPRESIONANTE .

Ahora bien, tal vez (léase: lo más probable es que sea así), soy muy tupido y no puedo entenderlo, pero he visto muchas veces esta pregunta sin una respuesta real. Muchas referencias a otros tutoriales o al libro de tipos de Commonsware. Sin embargo, los comentarios son viejos ahora y su repositorio ha cambiado tanto, que ya no son respuestas correctas.

Entonces, ¿alguien tiene alguna idea de cómo obtener la funcionalidad esperada de esto? O en su defecto, solo pásame el código fuente de la aplicación GMail. :)


Dentro del adaptador

viewHolder.radioBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e("called", "called"); if(position != mSelectedPosition && mSelectedRB != null){ mSelectedRB.setChecked(false); } mSelectedPosition = position; mSelectedRB = (RadioButton)v; } }); viewHolder.radioBtn.setText(mList[position]); if(mSelectedPosition != position){ viewHolder.radioBtn.setChecked(false); }else{ viewHolder.radioBtn.setChecked(true); if(mSelectedRB != null && viewHolder.radioBtn != mSelectedRB){ mSelectedRB = viewHolder.radioBtn; } }

agregar estilo al botón de radio

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tick" android:state_checked="true"/> <item android:drawable="@drawable/untick" android:state_checked="false"/> </selector>

y en el xml utiliza el estilo de botón de radio

<?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" > <RadioButton android:id="@+id/radioBtn" android:layout_width="match_parent" android:layout_height="50dp" android:button="@null" android:checked="true" android:drawablePadding="30dp" android:drawableRight="@drawable/checkmark" android:text="first" /> </RelativeLayout>


En tu adaptador:

public void setChecked(View v, int position) { ViewGroup parent = ((ViewGroup) v.getParent()); // linear layout for (int x = 0; x < parent.getChildCount() ; x++) { View cv = parent.getChildAt(x); ((RadioButton)cv.findViewById(R.id.checkbox)).setChecked(false); // your checkbox/radiobtt id } RadioButton radio = (RadioButton)v.findViewById(R.id.checkbox); radio.setChecked(true); }

En tu actividad / fragmento:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ((ModelNameAdapter)adapter).setChecked(view, position); } });


Mi nombre es Gourab Singha. He resuelto este problema. He escrito este código para resolverlo. Espero que esto los ayude a todos. Gracias. Necesito 3 horas para esto.

public void add_option_to_list(View v){ LinearLayout ll = (LinearLayout)v.getParent(); LinearLayout ll_helper = null; LinearLayout ll2 = (LinearLayout)ll.getParent(); LinearLayout ll3 = (LinearLayout)ll2.getParent(); ListView ll4 = (ListView)ll3.getParent(); //RadioButton rb1= (RadioButton)ll.getChildAt(1); Toast.makeText(getApplicationContext(), ", "+ll4.getChildCount(), Toast.LENGTH_LONG).show(); //ll.findViewById(R.id.radio_option_button) for(int k=0;k<ll4.getChildCount();k++){ ll3 = (LinearLayout)ll4.getChildAt(k); ll2 = (LinearLayout)ll3.getChildAt(0); ll_helper = (LinearLayout)ll2.getChildAt(0); RadioButton rb1 = (RadioButton)ll_helper.getChildAt(1); if(rb1.isChecked()) rb1.setChecked(false); } RadioButton rb1 = (RadioButton)ll.getChildAt(1); rb1.setChecked(true); //Toast.makeText(getApplicationContext(), ""+((TextView)ll.getChildAt(4)).getText().toString(), Toast.LENGTH_LONG).show(); }

El XML:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Category Name" android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone" /> <RadioButton android:id="@+id/radio_option_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="add_option_to_list" android:text="" /> <TextView android:id="@+id/option_name" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginLeft="3dp" android:layout_weight="5.35" android:text="Category Name" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/option_price" android:layout_width="76dp" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:gravity="right" android:text="$0.00" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/option_unit_price" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:gravity="right" android:text="$0.00" android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone" /> </LinearLayout> </LinearLayout> </LinearLayout>


Puedes lograr mucho más simple, sigue esto. Fue probado en MarshMallow

1) Tener un CheckedTextView :

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:padding="10dp" android:textAppearance="?android:attr/textAppearanceMedium">

  • ListChoiceIndicatorSingle mostrará RadioButton .

  • ListChoiceIndicatorMultiple mostrará CheckBox

No choiceMode:Single poner choiceMode:Single en tu ListView .


Solución simple:

Agregue esta línea en el diseño RadioButton de su archivo xml:

<RadioButton ... android:onClick="onClickRadioButton" ... />

Luego, en la clase de actividad que usa ListView, agregue lo siguiente:

private RadioButton listRadioButton = null; int listIndex = -1; public void onClickRadioButton(View v) { View vMain = ((View) v.getParent()); // getParent() must be added ''n'' times, // where ''n'' is the number of RadioButtons'' nested parents // in your case is one. // uncheck previous checked button. if (listRadioButton != null) listRadioButton.setChecked(false); // assign to the variable the new one listRadioButton = (RadioButton) v; // find if the new one is checked or not, and set "listIndex" if (listRadioButton.isChecked()) { listIndex = ((ViewGroup) vMain.getParent()).indexOfChild(vMain); } else { listRadioButton = null; listIndex = -1; } }

Con este código simple, solo se comprueba un RadioButton. Si toca el que ya está marcado, vuelve al modo no marcado.

"listIndex" está rastreando el elemento marcado, -1 si no hay ninguno.

Si desea mantener siempre una marcada, el código en OnClickRadioButton debe ser:

public void onClickRadioButton(View v) { View vMain = ((View) v.getParent()); int newIndex = ((ViewGroup) vMain.getParent()).indexOfChild(vMain); if (listIndex == newIndex) return; if (listRadioButton != null) { listRadioButton.setChecked(false); } listRadioButton = (RadioButton) v; listIndex = newIndex; }


Tenga en cuenta que en los elementos de la fila ListView están RECICLADOS. Es probable que esto explique por qué las acciones en una fila están afectando a otra. Busca en el libro de Mark y encontrarás cobertura de esto.

Si usa un adaptador con la lista, puede usar getView () en un adaptador para agregar un manejador de clics a cada fila a medida que se crea / recicla, y asegúrese de que el estado se administre correctamente a medida que los elementos de la fila se crean y reciclan .

Mi enfoque es almacenar el estado en mi propia estructura de datos y luego usar getView () para reflejar eso en la UI a medida que el usuario se desplaza hacia arriba y hacia abajo en ListView. Puede haber una solución mejor, pero eso funciona para mí.