Как использовать RadioGroup в пользовательском адаптере ListView? - PullRequest
39 голосов
/ 07 сентября 2011

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

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

"представление уже имеет родителя, вызовите removeView () в parent перед"

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

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

"представление уже имеет родителя, вызовите removeView () в parent до"

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

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>

It look like this if I not use RadioGroup

Ответы [ 7 ]

46 голосов
/ 15 сентября 2011

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

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

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

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

Вы должны сохранить ссылкудо последней проверенной радиокнопки, а затем при 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;
    }
}

Надеюсь, это поможет вам.

14 голосов
/ 13 мая 2012

Это моё решение.Это довольно просто.

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

    ...
}
2 голосов
/ 14 сентября 2011

Вы могли бы поставить

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 для позиции.

1 голос
/ 09 сентября 2011

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

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

Редактировать: не забудьте позвонить

 listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
0 голосов
/ 28 июля 2016

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

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

0 голосов
/ 09 сентября 2011

вам нужен тот же выход или другой ...

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

соответствует этому. Так что я приведу один пример для этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...