最近公司有需求实现一个签到功能,是ViewPager+RecyclerView+StaggerLayoutManager实现,其中有许多问题,经过查询资料和一遍遍测试,最后功能实现了,特别记录一下这个实现过程:
- 如何实现单选
先上效果图:
如何实现单选
因为我这里的存在多个RecylerView,括号内的内容可以忽略
(通过查询,都是单个RecylerView的单选,通过map记录每一个位置的选中状态,或者在数据原中,加入一个Boolean字段,在Adapter的onBindViewHolder中判断,是否是选中的,但是如果有多个数据源,怎么实现呢?)
使用一个map<String,Boolean>
将所有图片Url,和是否选中存储ok,
1.String 对应的是图片的Url
2.boolean 是这个图片是否选中
- 初始化数据
List<LinearLayout> layouts = new ArrayList<>();
//所有RecyclerView的Adapter
adapters = new ArrayList<>();
for (int i = 0; i < 4; i++) {
//======创建ViewPager中的每一个界面=======//
LinearLayout layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.widget_sign_item, null);
RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.sign_item_recyclerView);
//设置瀑布流LayoutManager
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
//RecyclerView的Adapter
StaggerRecylcerAdapter adapter = new StaggerRecylcerAdapter(context, list.get(i), map, map_heights);
recyclerView.setAdapter(adapter);
//设置item之间的间隔
SpacesItemDecoration decoration = new SpacesItemDecoration(16);
recyclerView.addItemDecoration(decoration);
layouts.add(layout);
adapters.add(adapter);
//遍历每一个图片的名字
for (int j = 0; j < list.get(i).getIcons().size(); j++) {
map.put(list.get(i).getIcons().get(j), false);
int random_height = (int) (100 + Math.random() * 200);
map_heights.put(list.get(i).getIcons().get(j), random_height);
}
}
//LayoutVPAdapter是自定义的ViewPager的adapter
LayoutVPAdapter adapter = new LayoutVPAdapter(layouts);
vp.setAdapter(adapter);
- LayoutVPAdapter
Viewpager的adapter,这里没什么好说的。
public class LayoutVPAdapter extends PagerAdapter {
private static final String TAG = "LayoutVPAdapter";
public static List<LinearLayout> layouts;
public LayoutVPAdapter(List<LinearLayout> layouts) {
this.layouts = layouts;
}
@Override
public int getCount() {
return layouts.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
LinearLayout layout = layouts.get(position);
ViewGroup parent = (ViewGroup) layout.getParent();
if (parent != null) {
parent.removeAllViews();
}
container.addView(layout, 0);
return layout;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(layouts.get(position));
}
}
- StaggerRecylcerAdapter
这里就是实现整个功能关键部分,
public class StaggerRecylcerAdapter extends RecyclerView.Adapter<StaggerRecylcerAdapter.MyViewHolder> {
private static final String TAG = "StaggerRecylcerAdapter";
private Context context;
private List<String> list;
private Map<String, Boolean> map;
private Map<String, Integer> map_hetights;
private String selectedIcon;
public StaggerRecylcerAdapter(Context context, GetIconBean.IconListBean.CategoryBean bean, Map<String, Boolean> map, Map<String, Integer> map_hetights) {
this.context = context;
this.list = bean.getIcons();
this.map = map;
this.map_hetights = map_hetights;
}
@Override
public StaggerRecylcerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
context).inflate(R.layout.sign_item_recycler_iv, parent,
false));
return holder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
// //判断是否为选中如果是选中,则显示checkbox(这里使用CheckBox进行边框设置)
for (String icon : map.keySet()) {
//判断map中与该页面中数据的Url相同的是否为选中
if (list.get(position).equals(icon)) {
//map.keySet()返回的是所有key的值
Boolean isSelect = map.get(icon);
if (isSelect) {
selectedIcon = icon;
holder.cb.setChecked(true);
holder.cb.setVisibility(View.VISIBLE);
}else {
holder.cb.setChecked(false);
holder.cb.setVisibility(View.GONE);
}
}
}
//设置图片使用的是Glide框架
for (String icon : map_hetights.keySet()) {
if (list.get(position).equals(icon)) {
//使用Glide展示图片
holder.setData(list.get(position), map_hetights.get(icon));
}
}
//点击图片进行选中与未选中状态切换
holder.iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//如果当前为选中的,那么让其不选中,如果是未选中那么让其变为选中
for (String icon : map.keySet()) {
if (list.get(position).equals(icon)) {
// 当第一次进入的时候,没有任何一个选中,此时,如果点击图片,就将该图片设置为选中的图片
if (Util.isNullOrBlank(selectedIcon)) {
selectedIcon = list.get(position);
}
map.put(icon, true);
} else {
map.put(icon, false);
}
}
//获取每一个Adapter,然后通知这些刷新界面
List<LinearLayout> layouts = LayoutVPAdapter.layouts;
List<StaggerRecylcerAdapter> adapters = ((SignActivity) context).getListAdapters();
//这个部分主要是修改当前可见页面的选中与未选中的切换,防止有"闪屏"
for (int k = 0; k < adapters.size(); k++) {
if (StaggerRecylcerAdapter.this == adapters.get(k)) {
RecyclerView recyclerView = (RecyclerView) layouts.get(k).findViewById(R.id.sign_item_recyclerView);
for (int j = 0; j < list.size(); j++) {
if (list.get(j).equals(selectedIcon)) {
//获取上一个选中的Item //利用 RecyclerView 的 findViewHolderForLayoutPosition()方法,获取某个postion的ViewHolder
MyViewHolder viewHolder = (MyViewHolder) recyclerView.findViewHolderForLayoutPosition(j);
if (viewHolder != null) {//还在屏幕里
//将上一个选中的变为未选中
Log.e(TAG, "selectedIcon==" + selectedIcon);
map.put(selectedIcon, false);
viewHolder.cb.setChecked(false);
viewHolder.cb.setVisibility(View.GONE);
}else {
notifyItemChanged(j);
}
//将现在选中的变为选中
selectedIcon = list.get(position);//更新选中项
Log.e(TAG, "new selectedIcon==" + selectedIcon);
map.put(list.get(position), true);
holder.cb.setChecked(true);
holder.cb.setVisibility(View.VISIBLE);
break;
}
}
} else {
adapters.get(k).notifyDataSetChanged();
}
}
}
});
}
@Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
ImageView iv;
CheckBox cb;
MyViewHolder(View view) {
super(view);
cb = (CheckBox) view.findViewById(R.id.item_recycler_cb);
iv = (ImageView) view.findViewById(R.id.item_recycler_iv);
}
void setData(String icon, int height) {
int width = ((Activity) iv.getContext()).getWindowManager().getDefaultDisplay().getWidth();
ViewGroup.LayoutParams params = iv.getLayoutParams();
//设置图片的相对于屏幕的宽高比
params.width = width / 2;
params.height = height;
iv.setLayoutParams(params);
ViewGroup.LayoutParams params_cb = cb.getLayoutParams();
params_cb.width = width / 2;
params_cb.height = height + 2;
cb.setLayoutParams(params_cb);
final RequestBuilder<Drawable> thumbnailRequest = Glide.with(context).load(R.drawable.launcher);
Glide.with(context).load(URLConstans.GET_ICON.ICON100 + icon).thumbnail(thumbnailRequest).into(iv);
}
}
}
实现后发现有选择第一排,然后滑动到最后,再选择一个,回到第一排,会发生图片item的跳动。
关于这个问题再另一篇文章中
http://blog.csdn.net/kenway090704/article/details/74352134