Android:自定义列表视图中的单选按钮
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21347661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: Radio button in custom list view
提问by Manoj Fegde
I am developing an application in which I need to implement radio buttons in list view. I want to implement a list view having one radio button and two text view in each row. And one button "Ok" below listview.
我正在开发一个应用程序,需要在列表视图中实现单选按钮。我想实现一个列表视图,每行有一个单选按钮和两个文本视图。和列表视图下方的一个按钮“确定”。
What I have done is I created a list view and a custom adapter. The code of listview is as:
我所做的是创建了一个列表视图和一个自定义适配器。列表视图的代码如下:
<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>
And I created a custom adapter layout as:
我创建了一个自定义适配器布局:
<?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>
The java code of fragment is as follows:
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) {}
And the code of adapter is as follows:
适配器代码如下:
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 rowView;
}
}
The data of textview1 are populated from SQLite database and on textview2 the data are "Status Closed". And on selection of or by clicking any radio button the text of text view get changed to "Status Open".
textview1 的数据是从 SQLite 数据库填充的,而 textview2 的数据是“状态关闭”。在选择或单击任何单选按钮时,文本视图的文本将更改为“状态打开”。
The Issue is:The need of application is that only one radio button should get select and data of textview2 get change on selection. And when user click on the other radio button it get select and the previous one should get deselect and text of textview2 get changed to "Status Closed" of a previously selected radio button and clicked radio button to "Status Open".
问题是:应用程序的需要是只有一个单选按钮应该得到选择并且 textview2 的数据在选择时得到改变。当用户单击另一个单选按钮时,它会被选择,并且前一个应该取消选择,textview2 的文本将更改为先前选择的单选按钮的“状态关闭”,然后单击单选按钮为“状态打开”。
Edit 1:
编辑1:
And onclick on "OK" button i want to get the position, text of list view textview1 and textview2, as i want to save that text in SQLite database in deview.
然后单击“确定”按钮,我想获取列表视图 textview1 和 textview2 的位置、文本,因为我想将该文本保存在 SQLite 数据库中。
Please guide me what steps should I follow. I am in middle of my application. Your valuable guidance is required.
请指导我应该遵循哪些步骤。我正在申请中。需要您的宝贵指导。
回答by Brian Attwell
Here are the key ideas
以下是关键思想
- when a
RadioButton
is checked we must callnotifyDataSetChanged()
, so that all views get updated. - when a
RadioButton
is checked we must set aselectedPosition
, to keep track of whichRadioButton
is selected View
s are recycled insideListView
s. Therefore, their absolute position changes in theListView
. Therefore, insideListAdapter#getView()
, we must callsetTag()
on eachRadioButton
. This allows us to determine the current position of theRadioButton
in the list when theRadioButton
is clicked.RadioButton#setChecked()
must be updated insidegetView()
for new or pre-existingView
s.
- 当 a
RadioButton
被选中时,我们必须调用notifyDataSetChanged()
,以便更新所有视图。 - 当 a
RadioButton
被选中时,我们必须设置 aselectedPosition
,以跟踪RadioButton
选择了哪个 View
s 在ListView
s内被回收。因此,它们的绝对位置在ListView
. 因此,在里面ListAdapter#getView()
,我们必须调用setTag()
每个RadioButton
。这允许我们RadioButton
在RadioButton
单击时确定列表中的当前位置。RadioButton#setChecked()
必须在内部更新getView()
新的或预先存在的View
s。
Here is an example ArrayAdapter I wrote and tested in order to demonstrate these ideas
这是我编写和测试的示例 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);
}
}
回答by Priyank Joshi
Try below adapter :
尝试以下适配器:
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;
}
}
And the layout that I am inflating is :
我膨胀的布局是:
<?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>
Here, I have used the checkbox, you can also use radiobutton instead of it, nothing else is needed to change.
在这里,我使用了复选框,您也可以使用单选按钮代替它,其他无需更改。
Hope it helps!
希望能帮助到你!