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

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

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

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

③最为关键的一步,即实现单选操作功能,在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;
	}
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需要强制转化为你自定义的对象
至此,该需求就实现了。

你可能感兴趣的:(Android)