美文网首页
仿微信朋友圈图片的九宫格效果

仿微信朋友圈图片的九宫格效果

作者: 蓝小默 | 来源:发表于2017-12-08 12:26 被阅读814次

前言

在写这个之前呢,我也百度(谷歌需要梯子)了一波,在github上也找了一番,实现的方式很多,还有很多封装好的库可以直接使用。鄙人有个习惯,就是很多东西都喜欢使用轻量级的,所以很多库的功能太全了,不符合鄙人的习惯。微信朋友朋友圈图片的九宫格效果并不难,尤其是RecyclerView如此强大的情况下,所以鄙人决定自己撸一个,不求功能多全面,满足自己的项目需求就好,于是就有了此文。

正文

没图说个鸡儿:


效果图

先照着朋友圈分析一下列表数据(只分析图片,视频跟单图其实是差不多的)的大概样子:

  • 头部下拉刷新(这个效果不在本文的考虑范围内);
  • 列表的图片大概分为单张,两列4张,三列N张;
  • 最多可以显示9张;
  • 单张图片自适应高度,宽度最大为列表宽度;
  • 多张图片为正方形图片,田字格或者九宫格。

所以我们可以把列表看做是三种viewType的集合,于是乎,我们的getViewType重写如下:


            int size ; // size的值是列表图片数量
            if (size < 2) {
              //没有图片或者单张图片
                return 1;
            } else if (size == 4) {
                //四张图片
                return 2;
            } else {
                //其他情况
                return 3;
            }

在onCreateViewHolder方法中,我们需要去创建我们的holder。其实四张图片的田字格可以当做是九宫格的一种特殊形式,当然一张图片也可以当做是九宫格的一种特殊形式,但鄙人将一张图片的情况跟九宫格的分开,那么我们就需要两个不同的holder去分别承载一张图和多张图的情况。多张图的情况,里面图片的列表我还是使用RecylcerView(RV简直不要太好用)。
对于总体的item来说,除了图片展示部分,其他的部分都是一样的,我们可以创建一个父类的holder,父类的holder提供了一个抽象的方法loadSelf ()提供给子类的holder去处理自己的逻辑。

abstract class ItemHolder extends RecyclerView.ViewHolder  {
       

        public ItemHolder(View itemView) {
            super(itemView);
           
        }

        private void setData(final int position, final CircleListModel model) {
            
            //todo 公共的逻辑
          

            loadSelf(position, model);
        }

        public abstract void loadSelf(final int position, final CircleListModel model);
    }

根据上面的分析,我们还需要创建两个子类的holder。

  • 提供给单张图片使用的:
private class OneHolder extends ItemHolder  {
        AppCompatImageView ivCover;
     
        public OneHolder(View itemView) {
            super(itemView);
            ivCover = itemView.findViewById(R.id.iv_cover);
        }

        @Override
        public void loadSelf(int position, CircleListModel model) {
            List<> mediaList ; //图片的数组
            // 如果没有图片,那就是只有文字,隐藏图片控件
            if (mediaList == null || mediaList.isEmpty()) {
                ivCover.setVisibility(View.GONE);
            } else {
                ivCover.setVisibility(View.VISIBLE);
               //todo 显示图片
                
            }
        }


  • 提供给多张使用的:
private class OtherHolder extends ItemHolder {
        RecyclerView rvItems;
        RAdapter<CircleListModel.CircleMsgMediaList> mAdapter;
        private ArrayList<CircleListModel.CircleMsgMediaList> mStrings = new ArrayList<>();

        public OtherHolder(final View itemView, int columns) {
            super(itemView);
            rvItems = itemView.findViewById(R.id.rv_items);

            mAdapter = new RAdapter<CircleListModel.CircleMsgMediaList>(mContext, R.layout.other_item, mStrings) {
                @Override
                protected void init(RViewHolder holder, final CircleListModel.CircleMsgMediaList circleMsgMediaList) {
                    LinearLayoutCompat.LayoutParams layoutParams = new LinearLayoutCompat.LayoutParams(widthPixels, widthPixels);
                    final AppCompatImageView image = holder.getView(R.id.image);
                    image.setLayoutParams(layoutParams);
                    //todo 加载图片

                    });

                }
            };
            GridLayoutManager manager = new GridLayoutManager(mContext, columns);
            rvItems.setLayoutManager(manager);
            rvItems.setAdapter(mAdapter);
            rvItems.addItemDecoration(new GridSpacingItemDecoration(columns, SPACE, false));
            rvItems.setHasFixedSize(true);
            ((SimpleItemAnimator) rvItems.getItemAnimator()).setSupportsChangeAnimations(false);

        }

        public void loadSelf(final int position, final CircleListModel model) {
            mStrings.clear();
            mStrings.addAll(model.getCircleMsgMediaList());
            mAdapter.notifyDataSetChanged();
        }
    }

上面的代码涉及到我自己封装Adapter和添加分割线的方法。老铁可以自己灵活的去换一下。

 ((SimpleItemAnimator) rvItems.getItemAnimator()).setSupportsChangeAnimations(false);

这一句不要忘了,不然会出现item闪烁的现象。

holder创建好了,下面就是onBindViewHolder()方法里面的代码了。由于上面封装的holder里面提供了setData()的方法,所以onBindViewHolder()方法里面的内容就简单多了:

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int p) {
        final int position = holder.getAdapterPosition();
        
            final CircleListModel model = mList.get(position);

            ((ItemHolder) holder).setData(position, model);
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //todo item点击事件
                }
            });
        }

    }

核心其实就调用holder的setData()方法和添加itemView的点击事件。

前面有讲到九宫格的情况下,图片展示的是方图,田字格是九宫格的一种特殊情况,上面OtherHolder 的构造方法里面需要传入图片格子的column,所以图片RecyclerView的宽度是wrap_content,那么我们需要手动的去实际计算一下图片的宽度。这个老铁们根据实际情况去计算就可以了。
另外还有一些交互的功能需要暴露出去,老铁们根据实际情况添加自己的接口就好了,比如我的:

public interface OnItemListener {
        void onItemClick(int position, CircleListModel t);

        void showComments(int position, CircleListModel t);

        void delete(int position, CircleListModel t);

        void onLinkClick(String url);
    }

到此效果就实现完了。

相关文章

网友评论

      本文标题:仿微信朋友圈图片的九宫格效果

      本文链接:https://www.haomeiwen.com/subject/ibdkixtx.html