带有广播组的大型自定义列表视图

时间:2015-02-05 07:03:39

标签: android

我是一名新的学习者。我正在开发一个需要50行或更多行的自定义列表视图的项目。每行包含一个表示行号的文本视图和一个有四个单选按钮的无线电组。问题是当我检查任何单选按钮然后向下滚动时,我看到许多单选按钮被自动检查。当向上滚动时,我会看到一些随机单选按钮被检查!

我猜它正在发生,因为getView()方法的循环问题说here。坦率地说,作为一个新手,我无法理解整个讲座。

我还查看了this线程。这与我的问题类似,但无法清楚地理解并解决我的问题。

那么如何解决这个问题并从无线电组中获取数据呢?由于我是新学员,请轻松解释。

谢谢!

[image]Here is my list view with a radio button checked of 1st row.

[image]When I scroll down I see 15th row is auto checked!

[image]When scroll up again I see radio group of the 1st row is in initial state again!

这是我的代码:

MainActivity:

public class MainActivity extends Activity {

    /* ListView */
    ListView lv;

    /* Data source for numbering */
    String[] numbering = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50"};

    /* Custom adapter */
    CustomListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /* initialization */
        adapter = new CustomListAdapter(this, R.layout.list_row_item, numbering);
        lv = (ListView) findViewById(R.id.lvQuestion);

        /* show list view */
        lv.setAdapter(adapter);
    }
}

list_row_item.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="horizontal" >

    <TextView
        android:id="@+id/tvNumbering"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <RadioButton
            android:id="@+id/answer0"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@drawable/radio_button"
            android:checked="true" />

        <RadioButton
            android:id="@+id/answer1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@drawable/radio_button" />

        <RadioButton
            android:id="@+id/answer2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@drawable/radio_button" />

        <RadioButton
            android:id="@+id/answer3"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@drawable/radio_button" />
    </RadioGroup>

</LinearLayout>

自定义列表适配器:

public class CustomListAdapter extends ArrayAdapter<String> {
    Context context;
    int layoutResourceId;
    String[] numbers;

    public CustomListAdapter(Context context, int layoutResourceId,
            String[] numbers) {
        super(context, layoutResourceId, numbers);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.numbers = numbers;
    }

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

        ViewHolder holder = null;

        if (convertView == null) {
            /* Add layout inflater */
            LayoutInflater infletar = ((Activity) context).getLayoutInflater();
            convertView = infletar.inflate(layoutResourceId, null);

            /* initialization */
            holder = new ViewHolder();
            holder.tvNumbering = (TextView) convertView
                    .findViewById(R.id.tvNumbering);
            holder.rg = (RadioGroup) convertView.findViewById(R.id.radioGroup);

            /* set tag */
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.tvNumbering.setText(numbers[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView tvNumbering;
        RadioGroup rg;
    }
}

1 个答案:

答案 0 :(得分:2)

调用getView后,您需要使用相关holder的数据初始化position中的观看次数。

您目前正在为该行中的TextView执行此操作。

holder.tvNumbering.setText(numbers[position]);

你需要为RadioGroup做同样的事情。

目前,CustomListAdapter被定义为ArrayAdapter Strings。因此,您转到适配器的项目列表是一个字符串数组,适配器为每个项目保留的唯一信息是每个项目的 数字 字符串的值项目

在您的情况下,您真正​​想要的是每个项目都有 数字 值和 选中的单选按钮 价值。

您应该提供一个自己的自定义类列表,而不是向适配器提供字符串列表,它会封装这两个变量。

public class MyItem {
    public String number;
    public int checkedRadioButtonId;
}

您需要让适配器处理此类。

public class CustomListAdapter extends ArrayAdapter<MyItem> {
    Context context;
    int layoutResourceId;
    MyItem[] items;

    public CustomListAdapter(Context context, int layoutResourceId,
                             MyItem[] items) {
        super(context, layoutResourceId, items);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.items = items;
    }

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

        View row = convertView;
        ViewHolder holder = null;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, null);
            holder = new ViewHolder(row);
            row.setTag(holder);
            // Set a listener to update the data in your items list when the RadioGroup is clicked
            holder.rowRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                public void onCheckedChanged(RadioGroup group, int checkedId) {

                    // **get which item this RadioGroup refers to**
                    Integer pos = (Integer) group.getTag();
                    Log.d("onCheckedChanged", "pos = " + pos + ", checkedId = " + checkedId);
                    items[pos].checkedRadioButtonId = checkedId;

                }
            });
        } else {
            holder = (ViewHolder) row.getTag();
        }

        // **Tag each RadioGroup so we know what item it refers to**
        holder.rowRadioGroup.setTag(position);

        // setup both views from the values stored in your items list
        holder.rowTextView.setText(items[position].number);
        holder.rowRadioGroup.check(items[position].checkedRadioButtonId);



        return row;
    }

    static class ViewHolder {
        TextView rowTextView = null;
        RadioGroup rowRadioGroup = null;

        ViewHolder(View row) {
            this.rowTextView = (TextView) row.findViewById(R.id.tvNumbering);
            this.rowRadioGroup = (RadioGroup) row.findViewById(R.id.radioGroup);
        }
    }
}

您的MainActivity会变得像

public class MainActivity extends Activity {

    /* ListView */
    ListView lv;

    /* Data source for the ListView */
    MyItem[] myItems = new MyItems[50];

    /* Custom adapter */
    CustomListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create the data for the list
        for (int i = 0; i < myItems.length; i++) {
            final MyItem item = new MyItem();
            // your numbering goes from 1 to 50, but the array indexes go from 0 to 49
            item.number = String.valueOf(i + 1); 
            // set all items to answer0 by default
            item.checkedRadioButtonId = R.id.answer0

            // put the new item in the array
            myItems[i] = item;
        }

        /* initialization */
        adapter = new CustomListAdapter(this, R.layout.list_row_item, myItems);
        lv = (ListView) findViewById(R.id.lvQuestion);

        /* show list view */
        lv.setAdapter(adapter);
    }
}