在做类似于投票或者试题的需求时,需要在listview中,一个item展示4个radiobutton,只能选中其中一个的需求,参考了这位博主的实现:
android listview radiogroup
不过这篇博客存在两个问题:一是4个radiobutton无法放在两行两列,只能竖直排列、二是滑动多次,radiobutton选中状态会混乱。
(1)主控制activity类MainActivity.java
(2)适配器adapter类:TopicAdapter.java
里面都有必要的注释,有问题可以交流,源码在此: 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混乱问题解决