Как использовать RadioGroup в пользовательском адаптере ListView?

Я хочу показать один вариант выбора в моем списке. Я использую RadioButton в своей строке listView. Я знаю, что RadioGroup используется для одиночного выбора.

Но проблема в том, что я добавил кнопку Radio в свой ListRowView. Теперь я хочу добавить все элементы списка в один RadioButton. Я использую пользовательский адаптер и getView (). Я получаю radobutton в getView (), когда хочу добавить его в RadioGroup, он говорит

"View allready have parent, вызовите removeView () в родительском элементе перед"

И я знаю его правду, но если я удалю его из представления. То это не видно.

Я также пытаюсь создать и добавить RadioButton программно. А затем добавьте его в RadioGrop. А затем просмотреть строку списка. Но на этот раз, когда родитель – RadioGroup, так снова говорят

"View allready have parent, вызовите removeView () в родительском элементе перед"

То, что я хочу сделать, – это выбрать только один элемент в списке за раз. Мой код выглядит следующим образом.

GetView

public class MyAdapter extends ArrayAdapter < MyMenuItem > { private LayoutInflater mInflater ; int mResource ; List < MyMenuItem > mData ; Context context; public MyAdapter ( Context context , int resource , int textViewResourceId , List < MyMenuItem > data ) { super ( context , resource , textViewResourceId , data ) ; this.context = context; mData = data ; mResource = resource ; mInflater = ( LayoutInflater ) getSystemService ( Context.LAYOUT_INFLATER_SERVICE ) ; } @ Override public View getView ( int position , View convertView , ViewGroup parent ) { ViewHolder holder = null ; if ( convertView == null ) { convertView = mInflater.inflate ( mResource , null ) ; holder = new ViewHolder ( ) ; holder.icon = ( ImageView ) convertView.findViewById ( R.id.icon ) ; holder.text = ( TextView ) convertView.findViewById ( R.id.text ) ; holder.comment = ( TextView ) convertView.findViewById ( R.id.comment ) ; LinearLayout lin = ( LinearLayout ) convertView.findViewById ( R.id.linerList ) ; RadioButton rbtn = new RadioButton ( context ); LayoutParams lparam = new LayoutParams ( LayoutParams.WRAP_CONTENT , LayoutParams.WRAP_CONTENT ); rbtn.setSelected ( false ); holder.check = rbtn; //radioGroup.addView ( rbtn ); lin.addView ( rbtn , 0 ); convertView.setTag ( holder ) ; } else { holder = ( ViewHolder ) convertView.getTag ( ) ; } holder.text.setText ( mData.get ( position ).getText ( ) ) ; holder.comment.setText ( mData.get ( position ).getComment ( ) ) ; holder.icon.setImageResource ( getApplicationContext ( ).getResources ( ).getIdentifier ( mData.get ( position ).getIcon ( ) , "drawable" , getPackageName ( ) ) ) ; return convertView ; } } 

Мой 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="?android:attr/listPreferredItemHeight" android:padding="6dip"> <LinearLayout android:id = "@+id/linerList" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="6dip" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_weight="1" android:layout_height="fill_parent"> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:text="My Application" android:textSize="20sp" android:singleLine="true" android:ellipsize="marquee" android:textColor="@color/white" /> <TextView android:id="@+id/comment" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:singleLine="true" android:ellipsize="marquee" android:text="Simple application that shows how to use RelativeLayout" android:textSize="14sp" android:textColor="@color/light_gray" /> </LinearLayout> 

Это выглядит так, если я не использую RadioGroup

Вам нужно сделать две вещи:

  1. Используйте mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  2. Сделайте свой пользовательский вид строки Checkable . (Подробнее об этом здесь ).

Это решение работает, и оно довольно чистое, но там могут быть некоторые лучшие решения.

Вы должны использовать свой адаптер для управления состоянием переключателей.

Вы должны сохранить ссылку на последнюю зарегистрированную радиокнопку, а затем на RadioButton.onClick вы установили последнюю установленную радиокнопку setChecked(false) .

Также не забудьте установить новый выбранный переключатель в качестве последнего выбранного переключателя.

См. Пример:

 private class MyAdapter extends ArrayAdapter<String>{ private int mResourceId = 0; private LayoutInflater mLayoutInflater; private RadioButton mSelectedRB; private int mSelectedPosition = -1; public MyAdapter(Context context, int resource, int textViewResourceId, List<String> objects) { super(context, resource, textViewResourceId, objects); mResourceId = resource; mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = convertView; ViewHolder holder; if(view == null){ view = mLayoutInflater.inflate(mResourceId, parent, false); holder = new ViewHolder(); holder.name = (TextView)view.findViewById(R.id.text); holder.radioBtn = (RadioButton)view.findViewById(R.id.radioButton1); view.setTag(holder); }else{ holder = (ViewHolder)view.getTag(); } holder.radioBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(position != mSelectedPosition && mSelectedRB != null){ mSelectedRB.setChecked(false); } mSelectedPosition = position; mSelectedRB = (RadioButton)v; } }); if(mSelectedPosition != position){ holder.radioBtn.setChecked(false); }else{ holder.radioBtn.setChecked(true); if(mSelectedRB != null && holder.radioBtn != mSelectedRB){ mSelectedRB = holder.radioBtn; } } holder.name.setText(getItem(position)); return view; } private class ViewHolder{ TextView name; RadioButton radioBtn; } } 

Надеюсь, он сделает это за вас.

Это мое решение. Это довольно легко.

my_radio_adapter_item.xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" ... /> <RadioButton android:id="@+id/radio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" ... /> </LinearLayout> 

MyRadioAdapter.java

 public class MyRadioAdapter extends BaseAdapter { private Context mContext; private ArrayList<Variation> mVariations; private int mSelectedVariation; public MyRadioAdapter(Context context, ArrayList<Variation> variations, int selectedVariation) { mContext = context; mVariations = variations; mSelectedVariation = selectedVariation; } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = convertView; if(view==null) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.my_radio_adapter_item, null); } final Variation variation = mVariations.get(position); TextView name = (TextView) view.findViewById(R.id.name); RadioButton radio = (RadioButton) view.findViewById(R.id.radio); name.setText(variation.getName()); if(position==mSelectedVariation) radio.setChecked(true); else radio.setChecked(false); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mSelectedVariation = position; MyRadioAdapter.this.notifyDataSetChanged(); } }); return view; } ... } 

Вы можете

 private int selectedIndex = -1; 

То в коде getView вы можете проверить

 if (position == selectedIndex) { rbtn.setSelected ( true ); } else { rbtn.setSelected ( false ); } 

И добавьте метод в свой пользовательский адаптер:

 public void setSelectedIndex(int index) { //some range-checks, maybe selectedIndex = index; //invalidate } 

Затем в вашем onItemClickedListener вы вызываете setSelectedIndex в позиции.

Вам нужно использовать CheckedTextView вместо обычного. http://developer.android.com/reference/android/widget/CheckedTextView.html

Я никогда не использовал его, но AlertDialog использует его для элементов SingleChoice. Так что это окончательно будет работать 🙂

Изменить: не забудьте позвонить

  listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 

Чтобы добавить к уже полученным ответам, для более модульного подхода, все элементы списка наследуются от того же класса / интерфейса, которые имеют функцию сообщения, которая позволит вам передавать им массаж через адаптер.
Адаптер регистрируется с каждым добавленным к нему элементом, поэтому каждый элемент списка может вызвать адаптер для отправки сообщения. То в прослушивателе RadioButton вы можете отправить сообщение всем другим переключателям, чтобы выключить, включить нажатый, затем, наконец, уведомить набор данных, измененный на адаптере.

У меня есть класс ListAdapter и абстрактный класс ListItem, которые достаточно надежны; Я пошлю всем, кому это нужно.
Поддерживается несколько типов элементов списка.

Вам нужен тот же результат или другой …

Я имею в виду, что вы выбрали только один из языков из списка. Это правильно?

Совместите его. Чтобы я привел один пример для этого