Android开发:在ListView中使用RadioGroup时出现混乱选中现象

     在做类似于投票或者试题的需求时,需要在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混乱问题解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值