【问题标题】:Android: Radio button in custom list viewAndroid:自定义列表视图中的单选按钮
【发布时间】:2014-02-16 07:57:59
【问题描述】:

我正在开发一个应用程序,我需要在其中实现列表视图中的单选按钮。我想实现一个列表视图,每行有一个单选按钮和两个文本视图。以及列表视图下方的一个“确定”按钮。

我所做的是创建了一个列表视图和一个自定义适配器。 listview的代码如下:

<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:cacheColorHint="#00000000"
    android:overScrollMode="never"
    tools:ignore="NestedScrolling"
    android:choiceMode="singleChoice" >
</ListView>

我创建了一个自定义适配器布局:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        tools:ignore="UselessParent" >

        <RadioButton
            android:id="@+id/radiobutton"
            android:layout_width="0sp"
            android:layout_height="wrap_content"
            android:layout_weight=".1" />

        <TextView
            android:id="@+id/textview1"
            android:layout_width="0sp"
            android:layout_height="wrap_content"
            android:layout_weight=".3" />

        <TextView
            android:id="@+id/textview2"
            android:layout_width="0sp"
            android:layout_height="wrap_content"
            android:layout_weight=".3" />

    </TableRow>

</TableLayout>

fragment的java代码如下:

ListView listView = (ListView) view.findViewById(R.id.listview);

// values is a StringArray holding some string values.
CustomAdapter customAdapter = new CustomAdapter (getActivity(), values);
listView.setAdapter(customAdapter );
listView.setOnItemClickListener(this);

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {}

而适配器的代码如下:

public class CustomAdapter extends ArrayAdapter<String> {   
    /** Global declaration of variables. As there scope lies in whole class. */
    private Context context;
    private String[] listOfValues;

    /** Constructor Class */
    public CustomAdapter (Context c,String[] values) {
        super(c,R.layout.adapter_layout,values);
        this.context = c;
        this.listOfValues = values;
    }

    /** Implement getView method for customizing row of list view. */
    public View getView(final int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        // Creating a view of row.
        View rowView = inflater.inflate(R.layout.adapter_layout, parent, false);
            
            TextView textView1 = (TextView)rowView.findViewById(R.id.textview1);
            TextView textView2 = (TextView)rowView.findViewById(R.id.textview2);

            RadioButton radioButton = (RadioButton) rowView.findViewById(R.id.radiobutton);

            radioButton.setOnClickListener(new OnClickListener() {          
            @Override   
            public void onClick(View v) {
                Toast.makeText(context, CustomAdapter[position], Toast.LENGTH_SHORT).show();
            }
        });
    
        return review;
    }
}    

textview1 的数据是从 SQLite 数据库填充的,而在 textview2 上的数据是“状态关闭”。在选择或单击任何单选按钮时,文本视图的文本将更改为“状态打开”。

问题是: 应用程序的需要是应该只选择一个单选按钮,并且 textview2 的数据在选择时会发生变化。当用户单击另一个单选按钮时,它会被选中,而前一个单选按钮应该被取消选择,textview2 的文本会更改为先前选择的单选按钮的“状态关闭”,然后单击单选按钮以“状态打开”。

编辑 1:

然后单击“确定”按钮,我想获取列表视图 textview1 和 textview2 的位置、文本,因为我想将该文本保存在审查中的 SQLite 数据库中。

请指导我应该遵循哪些步骤。我正在申请中。需要您的宝贵指导。

【问题讨论】:

    标签: android android-layout android-listview radio-button android-adapter


    【解决方案1】:

    这里是关键的想法

    • 检查RadioButton 时,我们必须调用notifyDataSetChanged(),以便更新所有视图。
    • 检查RadioButton 时,我们必须设置selectedPosition,以跟踪选择了哪个RadioButton
    • Views 在ListViews 内部回收。因此,它们的绝对位置在ListView 中发生变化。因此,在ListAdapter#getView() 内部,我们必须在每个RadioButton 上调用setTag()。这允许我们在单击RadioButton 时确定RadioButton 在列表中的当前位置。
    • RadioButton#setChecked() 必须在 getView() 内更新,以用于新的或预先存在的 Views。

    这是我编写和测试的一个示例 ArrayAdapter,以展示这些想法

    public class MainActivity extends ListActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // I do no use these values anywhere inside the ArrayAdapter. I could, but don't.
            final Integer[] values = new Integer[] {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,};
    
            ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, R.layout.row, R.id.textview, values) {
    
                int selectedPosition = 0;
    
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                    View v = convertView;
                    if (v == null) {
                        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                        v = vi.inflate(R.layout.row, null);
                        RadioButton r = (RadioButton)v.findViewById(R.id.radiobutton);
                    }
                    TextView tv = (TextView)v.findViewById(R.id.textview);
                    tv.setText("Text view #" + position);
                    RadioButton r = (RadioButton)v.findViewById(R.id.radiobutton);
                    r.setChecked(position == selectedPosition);
                    r.setTag(position);
                    r.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            selectedPosition = (Integer)view.getTag();
                            notifyDataSetChanged();
                        }
                    });
                    return v;
                }
    
            };
            setListAdapter(adapter);
        }
    }
    

    【讨论】:

    • 感谢您的建议。但我现在也面临困难。我是新手,所以我编辑了我的问题。现在你能帮我把这段代码放在哪里,以及如何使用它。您的指导对我很有价值。
    • 我添加了额外的代码来展示我如何使用 ArrayAdapter。您应该能够从我的代码中获得一个可以运行的应用程序,然后对其进行修改以用于您的目的。
    • 如果您对如何修改 SQLite 有任何疑问,您应该为此创建第二个问题。
    • 不要使用方法 notifyDataSetInvalidated();它将使您的列表视图无效并从顶部使用 notifyDataSetChanged(); 显示列表;
    • 布莱恩,干得好!感谢您的信息。能够将它与新的 recyclerview 一起使用,没有任何问题。
    【解决方案2】:

    试试下面的适配器:

    public class ChooseAdapter extends ArrayAdapter<LinkedHashMap<String, String>> {
    private ArrayList<LinkedHashMap<String, String>> listMenu;
    
    int position_id;
    
    private LayoutInflater inflater;
    Context context;
    
    public ChooseAdapter(Activity activity,
            ArrayList<LinkedHashMap<String, String>> listMenu, int type) {
    
        super(activity, R.layout.choose_single_item, listMenu);
        this.listMenu = listMenu;
    
        context = activity.getApplicationContext();
        inflater = LayoutInflater.from(context);
    
    }
    
    public int getCount() {
        return listMenu.size();
    }
    
    public long getItemId(int position) {
        return position;
    
    }
    
    public static class ViewHolder
    
    {
        public CheckBox chk;
    
    }
    
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder view;
    
        if (convertView == null) {
    
            view = new ViewHolder();
    
            convertView = inflater.inflate(R.layout.choose_single_item, null);
            view.chk = (CheckBox) convertView
                    .findViewById(R.id.selection_checkbox);
    
            view.chk.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    // TODO Auto-generated method stub
                    if (isChecked) {
    
                        listMenu.get((Integer) buttonView.getTag()).put(
                                "checked", "true");
                        for (int i = 0; i < listMenu.size(); i++) {
                            if (i != (Integer) buttonView.getTag()) {
                                if (listMenu.get(i).containsKey("checked"))
                                    listMenu.get(i).remove("checked");
                            }
                        }
                    } else {
                        listMenu.get((Integer) buttonView.getTag()).remove(
                                "checked");
                    }
    
                    notifyDataSetChanged();
                }
            });
    
            convertView.setTag(R.id.selection_checkbox, view.chk);
            convertView.setTag(view);
    
        }
    
        else {
            view = (ViewHolder) convertView.getTag();
        }
        view.chk.setTag(position);
    
        view.chk.setText(listMenu.get(position).get("name"));
    
        if (listMenu.get(position).containsKey("checked")) {
            view.chk.setChecked(true);
        } else
            view.chk.setChecked(false);
    
        return convertView;
    
    }
    }
    

    我正在膨胀的布局是:

    <?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="wrap_content"
    android:orientation="horizontal" >
    
    <CheckBox
        android:id="@+id/selection_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="abc"
        android:textColor="#8C8C8C"
        android:textSize="16sp" />
    
    </LinearLayout>
    

    这里我用了checkbox,你也可以用radiobutton代替它,其他什么都不需要改。

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2013-03-10
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      • 1970-01-01
      • 1970-01-01
      • 2014-03-13
      • 1970-01-01
      相关资源
      最近更新 更多