Android开发中动态向ListView中添加RadioButton和CheckBox以及动态改变其Checked状态改变(用心抒写)

匿名 (未验证) 提交于 2019-12-03 00:22:01

ListView作为Androd开发中最常用又最“多事”的组件,本人也是既爱之又“恨”之。

今天有一个需求:(测试题库中常用到的单选题,多选题等)

1、安卓自带的RadioButton,CheckBox太丑了,特别是当选项中出现大图片,ABCD之类的也得加到按钮后面,混合到一起,那是简直没法看了。所以,需要重新绘制RadioButton和CheckBox。

2、选项个数不确定,所以需要动态添加。

综上说述,决定用ListView+ListViewAdapter(自定义的,继承与BaseAdapter)来解决这个问题。

先上效果图:

思路:

看到上图样式,我们首先应该怎么做呢?因为,它有选中和不选中两个状态,第一个想到的就是:创建样式选择器selector以及做一下上图中的按钮背景图片。

如下代码:(其中,custom_rbutton_checked和custom_rbutton_unchecked分别是选中以及不选中时的按钮背景图)

<?xml version="1.0" encoding="utf-8"?> <!-- 单选按钮背景自定义效果 --> <selector xmlns:android="http://schemas.android.com/apk/res/android">      <item android:drawable="@drawable/custom_rbutton_checked" android:state_checked="true"         android:state_enabled="true" />     <item android:drawable="@drawable/custom_rbutton_unchecked" android:state_checked="false"         android:state_enabled="true" />  </selector>

然后在style.xml中添加相关RadioButton的样式。如下:(将背景设置为选择器的样式)

<style name="custom_radio_styles">         <item name="android:background">@drawable/selector_radiobutton_bg</item>         <item name="android:gravity">center</item>     </style>

接下来我们给相关布局文件中的RadioButton添加style样式即可。如下:

    <RadioButton         android:id="@+id/radiobuttonlist_singleChoiceButton"         style="@style/custom_radio_styles"         android:layout_width="30dp"         android:layout_height="30dp"         android:layout_marginRight="10dp"         android:button="@null"         android:focusable="false"         android:clickable="false"         android:focusableInTouchMode="false"         android:text="A" />
其中,
 android:button="@null"

可以把RadioButton的自带按钮样式去掉。

        android:focusable="false"         android:clickable="false"         android:focusableInTouchMode="false"

上面的可以解决ListView中添加Button或者CheckBox等时造成的ListView的onItemClickListener监听事件没反应的问题。(说白了就是焦点获取不到)

至此,按钮样式已经完成。下面我们开始做一下和ListView相关的操作。

首先,如果向ListView中添加子项,毋庸置疑,第一个想到的是不是数据适配器(ArrayAdapter,SimpleAdapter,BaseAdapter等)呢?这个大家应该都是这么想的,那么问题来了,用现有的SimpleAdapter适配器能够实现我们想要的展示出来的效果,但是想要的状态改变和数据改变,我们要怎么获取呢?想了想,行不通,那怎么办?那么我们自定义一个数据适配器就可以了,继承BaseAdapter。

如下图:RadioButtonListViewAdapter.java(单选题的数据适配器)

public class RadioButtonListViewAdapter extends BaseAdapter {      private List<ItemBean> mData;     private Context mContext;     private HashMap<String,Boolean> rButtonStates = new HashMap<String,Boolean>();      public RadioButtonListViewAdapter(Context mContext, List<ItemBean> mData, HashMap<String, Boolean> states) {         this.mContext = mContext;         this.mData = mData;         this.rButtonStates = states;     }      @Override     public int getCount() {         return mData.size();     }      @Override     public Object getItem(int position) {         return mData.get(position);     }      @Override     public long getItemId(int position) {         return position;     }      @Override     public View getView(int position, View convertView, ViewGroup parent) {         ViewHolder holder = null;         if (convertView == null) {             convertView = LayoutInflater.from(mContext).inflate(R.layout.item_radiobuttonlist, null);             holder = new ViewHolder(convertView);             convertView.setTag(holder);         } else {             holder = (ViewHolder) convertView.getTag();         }          final ItemBean itemObj = mData.get(position);         holder.textView.setText(itemObj.getText());         holder.radioButton.setText(itemObj.getBtnText());         boolean res = false;         if(getStates(position) == null || getStates(position) == false)//判断当前位置的radiobutton点击状态         {             res = false;             setStates(position, false);         }else{             res = true;         }         holder.radioButton.setChecked(res);         return convertView;     }      //用于在activity中重置所有的radiobutton的状态     public void clearStates(int position){         // 重置,确保最多只有一项被选中         for(String key:rButtonStates.keySet()){             rButtonStates.put(key, false);         }         rButtonStates.put(String.valueOf(position), true);     }     //用于获取状态值     public Boolean getStates(int position){         return rButtonStates.get(String.valueOf(position));     }     //设置状态值     public void setStates(int position, boolean isChecked){         rButtonStates.put(String.valueOf(position), false);     }      private class ViewHolder {         private RadioButton radioButton;         private TextView textView;          public ViewHolder(View convertView) {             radioButton = convertView.findViewById(R.id.radiobuttonlist_singleChoiceButton);             textView = convertView.findViewById(R.id.radiobuttonlist_singleChoiceContent);         }     } }

像其中的一些类以及item布局文件,大家可以自己定义即可。主要理解思路。

适配器整好了,那么我们现在在MainActivity中进行调用即可。

如下:(这是一个单选题选项动态添加的方法,在你需要的位置调用一下即可。)

//单选题选项添加     public void singleChoiceQuestionsAutoAddOption(int addNum, String userAnswer){         singleChoiceQuestionData = new ArrayList<ItemBean>();         HashMap<String, Boolean> optionStates = new HashMap<String, Boolean>();         for (int i = 0; i < addNum; i++) {             if (userAnswer.equals(optionTags[i])) {                 optionStates.put(String.valueOf(i), true);             } else {                 optionStates.put(String.valueOf(i), false);             }         }         for (int i = 0; i < addNum; i++){             ItemBean itemBean = new ItemBean();             itemBean.setBtnText(optionTags[i]);             itemBean.setText(singleChoiceQuestionsOptionContents[i]);             singleChoiceQuestionData.add(itemBean);         }         singleChoiceQuestionsAdapter = new RadioButtonListViewAdapter(this                 , singleChoiceQuestionData, optionStates);         singleChoiceQuestionsAdapter.notifyDataSetChanged();         rbList.setAdapter(singleChoiceQuestionsAdapter);     }

注意:因为做的是测试题库程序,所以用户的答案也要做保存以及切换题目的时候的用户答案显示。

最后,还要实现ListView的onItemClickListener的监听事件。

如下:

public AdapterView.OnItemClickListener singleChoiceAndMultipleChoiceQuestionsListviewOnItemClickListener             = new AdapterView.OnItemClickListener() {         @Override         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {             switch (questionType) {                 case 0:{                     singleChoiceQuestionsTransfer(view, position);                     userAnswers[0] = optionTags[position];                     break;                 }                 case 1:{                     multipleChoiceQuestionsTransfer(view, position);                     String userAnswer = userAnswers[1];                     String whichOption = optionTags[position];                     if (userAnswer.indexOf(whichOption) >= 0){                          userAnswer = userAnswer.replace(whichOption, "");                     }                     else {                         userAnswer = (userAnswer + whichOption).trim();                     }                     userAnswers[1] = userAnswer;                     break;                 }                 default:break;             }         }     };      private void singleChoiceQuestionsTransfer(View view, int position) {         RadioButton radioButton = (RadioButton) view.findViewById(R.id.radiobuttonlist_singleChoiceButton);         //每次选择一个item时都要清除所有的状态,防止出现多个被选中         singleChoiceQuestionsAdapter.clearStates(position);         radioButton.setChecked(singleChoiceQuestionsAdapter.getStates(position));         //刷新数据,调用getView刷新ListView         singleChoiceQuestionsAdapter.notifyDataSetChanged();      }

再重申一遍,代码已经很详细了,以理解为主,希望对大家有所帮助。大家互相学习,互相提升。

完整Demo地址:https://download.csdn.net/download/lpcrazyboy/10465373

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!