在做类似于投票或者试题的需求时,需要在listview中,一个item展示4个radiobutton,只能选中其中一个的需求,参考了这位博主的实现: android listview radiogroup
不过这篇博客存在两个问题:一是4个radiobutton无法放在两行两列,只能竖直排列、二是滑动多次,radiobutton选中状态会混乱。

1.第一个问题,如何让4个radiobutton按照两行两列,可以使用margin属性来调整,获取手机的宽度来实现平分宽度,参考我的这个链接:http://blog.csdn.net/nihaoqiulinhe/article/details/53943249

2.第二个选中混乱问题,原因是因为listview的复用机制导致,监听器的混乱,解决方式是每次取消掉监听器,使用hashmap保存选中的radiobutton位置,每次进行恢复就可以了。  参考国外的做法实现的,

链接为:http://stackoverflow.com/questions/20102820/radiogroup-buttons-loosing-its-state-after-listview-scroll贴出全部代码:
(1)主控制activity类MainActivity.java
package com.cxl.optiondemo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
 * 参考这位博主的源码http://blog.csdn.net/who0am0i/article/details/45200709 改进的地方如下:
 * 1.支持几行几列的radiobutton显示(不会随着手机分辨率而改变) 2.listview上下滑动radiobutton选中状态显示错乱的修复
 * @author nihaoqiulinhe
 * @createTime 2017年1月3日 下午2:01:12
public class MainActivity extends Activity {
	public Context context;
	private ListView topic_listview;
	private Button button_sent;
	private BaseAdapter mAdapter;
	private List<Map<String, TopicItem>> data = new ArrayList<Map<String, TopicItem>>();
	JSONObject data_json;
	String KEY = "list_topic_item";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_kyc_main);
		this.context = this;
		topic_listview = (ListView) findViewById(R.id.topic_quest_answer);
		mAdapter = new TopicAdapter(context, data);
		topic_listview.setAdapter(mAdapter);
		initData();
		getData();
		button_sent = (Button) findViewById(R.id.topic_sent_comment);
		button_sent.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String t = "";
				for (int i = 0; i < data.size(); i++) {
					t = t + "第 " + (i + 1) + " 题  ----------->您选择了【选项" + data.get(i).get(KEY).getUserAnswerId().trim() + "】 \n";
				Toast.makeText(context, t, Toast.LENGTH_SHORT).show();
	private void initData() {
		try {
			data_json = new JSONObject();
			data_json.put("result", "success");
			JSONArray array = new JSONArray();
			for (int i = 0; i < 10; i++) {
				JSONObject object = new JSONObject();
				object.put("questionId", "1");
				object.put("question", "康熙是乾隆的谁?");
				object.put("answerId", "");
				object.put("userAnswerId", "-1");
				JSONArray sarray = new JSONArray();
				JSONObject sobject1 = new JSONObject();
				sobject1.put("answerOption", "1");
				sobject1.put("answer", "儿子");
				sarray.put(sobject1);
				JSONObject sobject2 = new JSONObject();
				sobject2.put("answerOption", "2");
				sobject2.put("answer", "爷爷");
				sarray.put(sobject2);
				JSONObject sobject3 = new JSONObject();
				sobject3.put("answerOption", "3");
				sobject3.put("answer", "父亲");
				sarray.put(sobject3);
				JSONObject sobject4 = new JSONObject();
				sobject4.put("answerOption", "4");
				sobject4.put("answer", "孙子");
				sarray.put(sobject4);
				object.put("optionList", sarray);
				array.put(object);
			data_json.put("list", array);
		} catch (JSONException e) {
			e.printStackTrace();
	private void getData() {
		System.out.println(data_json.toString());
		data.clear();
		if (data_json.optString("result").equals("success")) {
			if (data_json.optJSONArray("list") != null) {
				for (int i = 0; i < data_json.optJSONArray("list").length(); i++) {
					JSONObject object = data_json.optJSONArray("list").optJSONObject(i);
					TopicItem topic = new TopicItem();
					topic.setAnswerId(object.optString("answerId"));
					topic.setQuestionId(object.optString("questionId"));
					topic.setQuestion(object.optString("question"));
					topic.setUserAnswerId(object.optString("userAnswerId"));
					List<OptionItem> optionList = new ArrayList<OptionItem>();
					for (int j = 0; j < object.optJSONArray("optionList").length(); j++) {
						JSONObject object_option = object.optJSONArray("optionList").optJSONObject(j);
						OptionItem option = new OptionItem();
						option.setAnswerOption(object_option.optString("answerOption"));
						option.setAnswer(object_option.optString("answer"));
						optionList.add(option);
					topic.setOptionList(optionList);
					Map<String, TopicItem> list_item = new HashMap<String, TopicItem>();
					list_item.put(KEY, topic);
					data.add(list_item);
				mAdapter.notifyDataSetChanged();

      (2)适配器adapter类:TopicAdapter.java
package com.cxl.optiondemo;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
 * 参考这位博主的源码http://blog.csdn.net/who0am0i/article/details/45200709 改进的地方如下:
 * 1.支持几行几列的radiobutton显示(不会随着手机分辨率而改变) 2.listview上下滑动radiobutton选中状态显示错乱的修复
 * @author nihaoqiulinhe
 * @createTime 2017年1月3日 下午2:01:12
public class TopicAdapter extends BaseAdapter {
	private static final String TAG = "TopicAdapter";
	String KEY = "list_topic_item";
	//四个listview的每个对应的getID状态
	private int optionID1, optionID2, optionID3, optionID4;
	private SparseIntArray checked = new SparseIntArray();//保存哪些radio被选中,相当于hashmap但效率更高
	private LayoutInflater mInflater;
	private Context context;
	private List<Map<String, TopicItem>> mData;//数据源
	public TopicAdapter(Context context, List<Map<String, TopicItem>> data) {
		mData = data;
		mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		this.context = context;
		init();
	private void init() {
		mData.clear();
	@Override
	public int getCount() {
		int count = mData == null ? 0 : mData.size();
		return count;
	@Override
	public Object getItem(int position) {
		 * Object obj = records != null && records.size() > position ?
		 * records.get(position) : null; return obj;
		return null;
	@Override
	public long getItemId(int position) {
		//return position;
		return 0;
	private Integer index = -1;
	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		Holder holder = null;
		if (convertView == null) {
			convertView = mInflater.inflate(R.layout.activity_kyc_item, null);
			holder = new Holder();
			holder.question = (TextView) convertView.findViewById(R.id.topic_item_question);
			holder.option = (RadioGroup) convertView.findViewById(R.id.topic_item_option);
			holder.option1 = (RadioButton) convertView.findViewById(R.id.topic_item_option1);
			optionID1 = holder.option1.getId();
			holder.option2 = (RadioButton) convertView.findViewById(R.id.topic_item_option2);
			optionID2 = holder.option2.getId();
			//为了能够在一行显示两个radiobutton:获取屏幕的宽度
			WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
			int width = wm.getDefaultDisplay().getWidth();//左侧设置的间距
			int height = DensityDpToPx.dpToPx(context, 24);//处于第二个的高度间距
			LinearLayout.LayoutParams params = (LayoutParams) holder.option2.getLayoutParams();
			params.setMargins(width / 2, -height, 0, 0);
			holder.option2.setLayoutParams(params);
			holder.option3 = (RadioButton) convertView.findViewById(R.id.topic_item_option3);
			optionID3 = holder.option3.getId();
			holder.option4 = (RadioButton) convertView.findViewById(R.id.topic_item_option4);
			optionID4 = holder.option4.getId();
			LinearLayout.LayoutParams paramsTwo = (LayoutParams) holder.option4.getLayoutParams();
			paramsTwo.setMargins(width / 2, -height, 0, 0);
			holder.option4.setLayoutParams(paramsTwo);
			holder.option.setTag(position);
			holder.option.setOnTouchListener(new OnTouchListener() {
				@Override
				public boolean onTouch(View v, MotionEvent event) {
					if (event.getAction() == MotionEvent.ACTION_UP) {
						index = (Integer) v.getTag();
					return false;
			convertView.setTag(holder);
		} else {
			holder = (Holder) convertView.getTag();
			holder.option.setTag(position);
		//在显示RadioButton值之前,取消对其监听,否则会出现混乱的效果。
		holder.option.setOnCheckedChangeListener(null);
		holder.option.clearCheck();
		if (checked.indexOfKey(position) > -1) {
			holder.option.check(checked.get(position));
		} else {
			holder.option.clearCheck();
		holder.option.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(RadioGroup group, int checkedId) {
				if (checkedId > -1) {
					checked.put(position, checkedId);
					TopicItem item = mData.get(position).get(KEY);
					int RadioButtonId = group.getCheckedRadioButtonId();
					if (RadioButtonId == optionID1) {
						item.setUserAnswerId(item.getOptionList().get(0).getAnswerOption().trim());
					} else if (RadioButtonId == optionID2) {
						item.setUserAnswerId(item.getOptionList().get(1).getAnswerOption().trim());
					} else if (RadioButtonId == optionID3) {
						item.setUserAnswerId(item.getOptionList().get(2).getAnswerOption().trim());
					} else if (RadioButtonId == optionID4) {
						item.setUserAnswerId(item.getOptionList().get(3).getAnswerOption().trim());
					mData.get(position).put(KEY, item);
				} else {
					if (checked.indexOfKey(position) > -1) {
						checked.removeAt(checked.indexOfKey(position));
		TopicItem item = mData.get(position).get(KEY);
		if (item != null) {
			//防止afterTextChanged自动执行
			holder.question.setText(item.getQuestion());
			holder.option1.setText(item.getOptionList().get(0).getAnswer().toString());
			holder.option2.setText(item.getOptionList().get(1).getAnswer().toString());
			holder.option3.setText(item.getOptionList().get(2).getAnswer().toString());
			holder.option4.setText(item.getOptionList().get(3).getAnswer().toString());
		holder.option.clearFocus();
		if (index != -1 && index == position) {
			holder.option.requestFocus();
		return convertView;
	private class Holder {
		private TextView question;
		private RadioGroup option;
		private RadioButton option1;
		private RadioButton option2;
		private RadioButton option3;
		private RadioButton option4;

      (3)界面文件:activity_kyc_main.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="vertical" >
    <ListView
        android:id="@+id/topic_quest_answer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          android:layout_weight="1"
        android:layout_marginTop="16dp" >
    </ListView>
    <LinearLayout
        android:id="@+id/kyc_confirm_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        android:layout_weight="9"
        android:orientation="horizontal"
        android:visibility="visible" >
        <Button
            android:id="@+id/topic_sent_comment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="6dp"
            android:background="@drawable/comment_btu" />
    </LinearLayout>
</LinearLayout>

     运行结果为:

      
    里面都有必要的注释,有问题可以交流,源码在此: android listview radiogroup混乱问题解决 背景一个典型的ListView,每个Item显示一个TextView,代表一个Task,需要实现二个编辑方式:一个是用CheckBox来标识任务已经完成,另一个要实现的编辑是删除任务。对于完成的CheckBox就直接放在布局就可,但对于删除不想使用ContextMenu来实现编辑,对于像iOS那样的列表,它的删除都是通过对列表每个项目的手势来触发。这个实现起来并不难,可以用一个ViewSwitcher,Checkbox和删除按扭是放入其,让ViewSwitcher来控制显示哪一个,正常情况下显示Checkbox,隐藏删除按扭,然后当点击Item就显示删除按扭,隐藏Checkbox,这 本文实例讲述了Android编程开发ListView的常见用法。分享给大家供大家参考,具体如下: 一、ListView使用步骤 ListView使用通常有以下三个要素: (1)ListView每个条目的布局; (2)填充进入ListView的内容; (3)将内容与页面进行整合的Adapter. 因此,使用ListView也通常有以下三个步骤: (1)创建ListView条目的布局文件(或使用Android SDK提供的布局); (2)创建填充进入ListView的内容,如字符串、图片等; (3)创建Adapter并将其与ListView绑定. 二、使用默认的布局文件创建ListVi 前几天因为项目的需要,要在一个ListView放入另一个ListView,也即在一个ListView的每个ListItem放入另外一个ListView。但刚开始的候,会发现放入的小ListView会显示不完全,它的高度始终有问题。上网查了下,发现别人也有遇到这样的问题,而大多数人都不推荐这样的设计,因为默认情况下Android是禁止在ScrollView放入另外的ScrollView的,它的高度是无法计算的。又搜索了一下,发现有StackOverflow上的牛人已经解决了这个问题,经过试验发现是可以解决问题的,它的思路就是在设置完ListView的Adapter后,根据ListView 一、直接使用ListView组件创建 1.直接在XML创建ListView用entries属性附上一个数组资源 其divider属性是设置分割线可以使用颜色和drawable资源分割 <ListView android:id=@+id/listView1 android:layout_width=match_parent android:layout_height=wrap_content android:divider=#33000000 android:dividerHeight=0.2dp android:fo I cannot seem to get around the idea if some property i.e. has_tv is empty or in other words a RadioGroup that has been left empty by user, how can I request focus to that particular view using data b... Android开发listview+radiobutton实现单选(选项可编辑) 昨天刚写完APP新增的小功能(功能如标题),感觉挺多地方都用的到,就独立出来写了一个Demo,分享给大家,也当是温故总结一下。 知识点:之前有大神归纳过了,详情戳链接 http://blog.csdn.net/fznpcy/article/details/8658155/ 简介:Activity两个控件... 许久没有写过博客了,近来在做Android开发,突然想到这里,以后可以在这里贴些代码,做些记录,与大家分享交流。Android开发,常常会用到RadioButtonListView的混合使用,用户点击一条Item,然后记录下选中的状态,其最重要的是记录好用户点击选中Item的位置。布局文件很简单:xmlns:tools="http://schemas.android.com/tools"an... 本篇博客要给大家分享的是在Android开发遇到滑动数据错乱的问题如何解决,先描述一些为什么会出现数据错乱,熟悉ListView复用原因的朋友一定知道,我们在开发为了优化数据显示,避免卡顿,会利用ListView的缓存机制来复用我们的View。  来看一段我们经常会写的代码: package com.xiaowu.adapter; import com.xiaowu.acti 上面显示的是我的TextViews和RadioGroup的自定义列表视图.根据项目状态是“待处理”还是“提供”,我更新待处理项目 – TextView(红色,顶部).一切都按预期工作,我能够在滚动保留RadioGroup选择.但是,当我滚动,挂起的项TextView不会保留其值.只要列表滚动,它就会改变.这是我的getView方法.public View getView(final int ... 在做项目,有这样的需求:ListView列表的adapter布局有两个RadioButton,但是要求这两个RadioButton必须是单选的,所有就加入了RadioGroup,也是是这样的,要保证单选,获取选中RadioButton的值,而且ListView的Item还有其它用。不得不说需求有点坑爹,一般都是checkBox全选,但程序员没办法,只能照着客户的需求来做。在网上也找了很多资料, 当我们在使用ListView候,一般都会在getView()方法里面使用item复用的方式,如下:ViweHolder view = null;if(convertView == null){...}....return convertVew;当我们在Item有RadioGroup控件 ,或是需要有其他条件来判断当前Item是否需要展示一个或多个控件,当我们随意滑动ListView你会发现本...