Android ListView中点击单行实现RadioButton的单选功能,自定义Item布局文件

时间:2021-11-06 17:55:17

Android ListView中点击单行实现RadioButton的单选功能,自定义Item布局文件

  需求描述:Android的ListView中,在自定义的Item中添加RadioButton来指示选中的某个单行,要求点击单行而不是RadioButton就触发选择功能。 ①在包含ListView的layout文件中,将ListView元素属性设置为单选模式android:choiceMode="singleChoice"
 <ListView
android:id="@+id/lvRegular"
android:dividerHeight="1px"
android:layout_width="match_parent"
android:choiceMode="singleChoice"
android:layout_height="wrap_content" >
</ListView>

②在ListView对应的Item的布局文件中,RadioButton元素设置不可点击属性android:clickable="false"这样可以屏蔽掉RadioButton的点击就会(取消)勾选的默认动作, 同时该布局的根元素设置android:descendantFocusability="blocksDescendants"以确保焦点只在根元素上。 这样就可以点击行实现(取消)勾选功能。
        <RadioButton
            android:id="@+id/regularRadio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:clickable="false"
            android:layout_gravity="right" />

③最为关键的一步,即实现单选操作功能,在Adapter中实现
自定义的RegularAdapte继承BaseAdapter,其他方法不写,这里只贴出关键代码getView()
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
final int mPosition = position;
if (convertView == null) {
v = mInflater.inflate(R.layout.item_load_fragment_list_car, parent,
false);
} else {
v = convertView;
}
//Log.v("Regular", position + " " + v.hashCode() + " " + checkedPosition);
Regular r = (Regular) getItem(position);
((TextView) v.findViewById(R.id.regularNo)).setText(r.get_ccbh());
((TextView) v.findViewById(R.id.regularCph)).setText(r.get_cph());
((TextView) v.findViewById(R.id.regularFcsj)).setText(r.get_fcsj());
((TextView) v.findViewById(R.id.regularLc)).setText(r.get_lc() + "km");
((TextView) v.findViewById(R.id.regularXlmc)).setText(r.get_xlmc());
final RadioButton rb = (RadioButton) v.findViewById(R.id.regularRadio);
rb.setChecked(mPosition == checkedPosition);
//请在xml文件中在根元素设置屏蔽焦点属性,以及在radioButton中设置不可点击事件
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkedPosition == mPosition)
checkedPosition = -1;
else
checkedPosition = mPosition;
// rb.setChecked(curPosi==checkedPosition);//此行代码可以略去,见最后一行代码
// 回传数据给fragment
mFragment.onItemClick(checkedPosition);
// 下面一行代码非常重要,重新调用getView()刷新可见区域的view,达到动态刷新的目的,不用担心性能问题,
// 因为仅仅只是重新填充数据而不会重新绘制view(有这个作判断convertView == null)
RegularAdapter.this.notifyDataSetChanged();
}
});
return v;
}<pre name="code" class="java">private int checkedPosition = -1;// 用于标识选中的radiobutton 的位置
//自定义内部接口
public interface OnItemClickListener{
void onItemClick(int position);
}

实现思路是用一个字段checkedPosition来标识已经选择的单项,position是唯一的,因此记录它即可。
RegularAdapter.this.notifyDataSetChanged();//这行代码太关键了,有了它,完美解决了RadioButton错乱的问题                另外要明白一点的是getView()的执行时机,一般而言当超出屏幕显示范围的项,重新回到显示范围内时,getView()会被执行,这样通过 rb.setChecked(mPosition == checkedPosition); 来确定RadioButton的状态,由于convertView有了null的判断,达到了复用的目的,getView()方法的执行不会         带来太大的性能问题,只是重新填充了数据而已,并且convertView还会缓存一部分数据(好像12项)。 至此,在Adapter中非常简单的实现了单选功能,那么在Activity或者fragment中如何取得选中的行的对象呢?                mFragment.onItemClick(checkedPosition);//这是个回调函数,通过它,将当前选中的行的唯一表示position回传给Fragment或Activity,此处mFragment是fragment 这需要在Adapter中定义一个内部接口,名字随便取,这里为OnItemClickListener接口。 接下来在Fragment或者Activity中实现该接口,并同样定义属性private int checkedPosition = -1;// 用于标识选中的radiobutton 的位置 在其实现接口的方法中同步赋值即可。这样就完成了回传功能。
@Override
public void onItemClick(int currentPosition) {
checkedPosition = currentPosition;
}
然后就可以Fragment或Activity中这样取得选中行的对象
            Object obj = listview.getItemAtPosition(checkedPosition);//obj需要强制转化为你自定义的对象 至此,该需求就实现了。