这个图片选择界面使用了support v7里的一个控件RecyclerView并且做了多选功能。
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="1dp"> <ImageView android:id="@+id/adapter_image_imageview" android:contentDescription="@null" android:layout_width="match_parent" android:layout_height=" match_parent" android:scaleType="centerCrop"/> <CheckBox android:id="@+id/adapter_image_checkbox" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="#80000000" android:maxLines="1" android:ellipsize="end"/> |
图的右边是Item Layout,在一个ReletiveLayout里用ImageView显示图片,底部叠了一层半透的CheckBox用来显示图片Title和选择图片。多选的思路是在Item的显示数据里(Model)添加一个是否选择的信息,在Item视图里(View)添加相应的处理。
Adapter的显示数据 static class ItemData { int id; String type; String title; ItemData(int id, String type, String title, boolean selected) { this.id = id; } |
onBindViewHolder里根据Item的selected数据设置CheckBox。设置点击侦听,CheckBox状态发生变化则更新该Item的显示数据selected值。 @Override String title = data.title; holder.checkbox.setText(title); holder.checkbox.setOnCheckedChangeListener(null); holder.checkbox.setChecked(selected); holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { //int position = holder.getAdapterPosition(); refData.get(position).selected = isChecked; } |
此时代码已经能够实现点击多选的功能。
这里有一个细节,CheckBox侦听器里使用onBindViewHolder传来的参数position时Android Studio的代码检查发出了警告如下图:
"Do not treat position as fixed; only use immediately and call holder.getAdapterPosition() to look it up later"。对于这条检查警告的的原因,我查阅了RecycleView.Adapter的文档。
适配器方法public void onBindViewHolder(AdapterImageAsync.ItemView holder, int position) 的文档说明: Called by RecyclerView to display the data at the specified position. This method should update the contents of the ViewHolder to reflect the item at the given position. Note that unlike ListView, RecyclerView will not call this method again if the position of the item changes in the data set unless the item itself is invalidated or the new position cannot be determined. For this reason, you should only use the position parameter while acquiring the related data item inside this method and should not keep a copy of it. If you need the position of an item later on (e.g. in a click listener), use ViewHolder.getAdapterPosition() which will have the updated adapter position. 文档的Note说: 与ListView不同,如果Item的位置在数据集中变化,RecyclerView将不会再次调用此方法,除非Item本身无效或新位置无法确定。 因此,只能在此方法中的获取相关数据时使用position参数,并且不应保留其副本。 如果稍后需要某个Item的位置(例如在点击监听器中),使用具有更新的适配器位置的ViewHolder.getAdapterPosition()。 |
所以这里的CheckBox侦听应该这么写,此时代码检查已经是 0 warning
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int data_position = holder.getAdapterPosition(); refData.get(data_position).selected = isChecked; |