美文网首页
RecyclerView显示系统所有图片表格排列并可选中大图显示

RecyclerView显示系统所有图片表格排列并可选中大图显示

作者: 撕裂的我 | 来源:发表于2017-08-30 17:39 被阅读0次
    4355782-dc04eb85215d55f5.gif

    动画效果如上,主要是获取到系统所有的图片显示出来,在头部大图显示被选中的图片,底部系统图片能上滑覆盖大图,要记录图片被选中的顺序,最多只能选中9张图片,选中有数字提示。

    先进行实现该效果的大概步骤分解。1.先实现UI效果,有表格首选RecyclerView;2.获取系统的所有图片;3.将获获取到的图片设置到RecyclerView中;4实现选中数字的标识和大图的显示。

    1.UI效果

    直接用RecyclerView来显示,直接看代码吧。

     mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
            mPicContainer = (LinearLayout) findViewById(R.id.pic_container);
            GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 4);
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (position == 0) {
                        return 4;
                    } else {
                        return 1;
                    }
                }
            });
            mRecyclerView.setLayoutManager(gridLayoutManager);
            mRecyclerView.setAdapter(new MyAdapter(this, mData));
    

    下面是Adapter

    class MyAdapter extends RecyclerView.Adapter {
        private Context mContext;
        private List<String> mData;
    
        public MyAdapter(Context context, List<String> data) {
            mContext = context;
            mData = data;
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == 1) {
                View view = LayoutInflater.from(mContext).inflate(R.layout.item_head, parent, false);
                return new HeadViewHolder(view);
            } else {
                View view = LayoutInflater.from(mContext).inflate(R.layout.item_body, parent, false);
                return new BodyViewHolder(view);
            }
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof HeadViewHolder) {
                return;
            } if (holder instanceof BodyViewHolder){
                setBodyViewHolder(holder, position);
            }
        }
    
        private void setBodyViewHolder(RecyclerView.ViewHolder holder, int position) { 
            String path = mData.get(position - 1);
            ImageUtil.getInstance().displayImage(mContext, path, ((BodyViewHolder) holder).image, R.color.colorPrimary);//显示出图片
    
        }
    
        @Override
        public int getItemCount() {
            return mData == null || mData.size() == 0 ? 0 : mData.size();
        }
    
        @Override
        public int getItemViewType(int position) {
            return position == 0 ? 1 : 2;
        }
    
         class HeadViewHolder extends RecyclerView.ViewHolder {
            public HeadViewHolder(View view) {
                super(view);
            }
        }
    
         class BodyViewHolder extends RecyclerView.ViewHolder {
            public ImageView image;
    
            public BodyViewHolder(View view) {
                super(view);
                image = (ImageView) view.findViewById(R.id.item_body);
            }
        }
    }
    

    Adapter中主要是要将第一个item,及position为0时,显示一个4个item宽度的一个透明的head,这样就不会挡住大图显示的区域。


    1504062832(1).jpg

    2.获取到系统所有的图片

    private void getAllPics() {
            mDataBeanList = new ArrayList<>();
            mData = new ArrayList<>();
            ContentResolver contentResolver = getContentResolver();
            DataBean dataBean = null;
            Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA}, MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?", new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media._ID + " DESC");
            while (cursor.moveToNext()) {
                String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                File file = new File(path);
                if (file.exists()) {
                    dataBean = new DataBean();
                    dataBean.filePath = path;
                    mData.add(path);
                    mDataBeanList.add(dataBean);
                }
            }
            cursor.close();
        }
    

    是通过内容解析者来获取到图片,然后通过cursor去遍历。

    3.将获取到的图片设置到RecyclerView中

    这一步相对来说就比较简单了,我们在第2步中已经得到了系统中所有的图片的路径,现在只需要将图片显示出来就可以了。这里我借用了雷哥一个ImageUtil图片工具类,封装了显示各种图片(本地,网路等)的方法,内部是通过Glide来实现的,现在直接拿来用。

    private void setBodyViewHolder(RecyclerView.ViewHolder holder, int position) { 
            String path = mData.get(position - 1);
            ImageUtil.getInstance().displayImage(mContext, path, ((BodyViewHolder) holder).image, R.color.colorPrimary);//显示出图片
    
        }
    

    这里需要注意的是我们需要将position-1,因为我们留了一个透明的head。到这里为止我们就实现了显示系统所有的图片了。

    4.实现选中数字的标识和大图的显示

    点击MyAdapter中的数据,需要在MainActivity中去显示,我这里用了接口回调。

    ((BodyViewHolder) holder).image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickListener != null) {
                        mOnItemClickListener.onItemClick(position - 1);
                    }
                }
            });
        }
    //    接口回调用来大图显示被选中的图片
        OnItemClickListener mOnItemClickListener;
        public interface OnItemClickListener {
             void onItemClick(int position);
        }
        public void setOnItemClickListener(OnItemClickListener onItemClickListener){
            mOnItemClickListener = onItemClickListener;
        }
    

    需要注意的事,这里需要考虑Head的position,所以将position-1。
    在MAinActivity中调用该接口。

    //        接口回调显示被选中的图片
            myAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(int position) {
    //                这里的position已做了-1的处理
                    showBigPic(position);
                }
            });
    }
    
    private void showBigPic(int position) {
            Bitmap bitmap = BitmapFactory.decodeFile(mData.get(position));
            int height = bitmap.getHeight();
            ViewGroup.LayoutParams layoutParams = mPicContainer.getLayoutParams();
    //        计算缩放比例
            float sca = layoutParams.height * 1.0f / height;
    //        根据高度来确定宽度
            layoutParams.width = (int) (bitmap.getWidth() * sca);
    //        防止重复
            mPicContainer.removeAllViews();
            ImageView imageView = new ImageView(this);
            imageView.setLayoutParams(layoutParams);
    //        imageView.setLayoutParams(new ViewGroup.LayoutParams(layoutParams));
            ImageUtil.getInstance().displayImage(this,mData.get(position),imageView,R.color.colorPrimary);
            mPicContainer.addView(imageView);
        }
    

    为了避免图片变形,这里进行了缩放比例的计算。到这里我们已经完成了大部分的功能了,可以显示所有的系统图片,也能大图显示选中的图片。
    最后一步就是显示右上角的选中顺序了。

    4.1完成选中的数字逻辑

    为了完成相应的逻辑,每一个图片都需要赋值多个属性,为了方便,我选择创建了一个Bean对象,这样能够更加简洁。

    public class DataBean {
        public String filePath;
        public boolean isSelected; //是否已经被选中
        public int selectedNum; //被选中的顺序
    }
    

    在接口回调的点击事件中做判断,看被点击的dateBean的isSelected是否为true,如果是true代表是选中的状态,再次点击取消选中,需要注意的事MyAdapter中的position对应DataBean集合中的position相差1(因为MyAdapter中有一个透明head)。

     mMyAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(int position) {
                    DataBean dataBean = mDataBeanList.get(position - 1);
    //                这里的position已做了-1的处理
                    showBigPic(dataBean);
    //                已经被选中,再次点击需要取消选中,数字也要相应改变
                    if (dataBean.isSelected) {
                        cancel(dataBean);
                    } else {
    //                    点击之前没有别选中
                        selected(dataBean);
    //                    更新被选中的item
                        mMyAdapter.notifyItemChanged(position);
                    }
                }
            });
    
      private void selected(DataBean dataBean) {
            selectedNum++;
    //        将所有被选中的dataBean放在一个集合中,便于去比较selectedNum
            mMyAdapter.selectedBean.add(dataBean);
            dataBean.isSelected = true;
            dataBean.selectedNum = selectedNum;
        }
    
        private void cancel(DataBean dataBean) {
            selectedNum--;
    //        遍历选中的dataBean,比较被点击的这个bean的selectedNum和其他selectedNum的大小,比它大的都要-1
            for (int i = 0; i < mMyAdapter.selectedBean.size(); i++) {
                int z = dataBean.selectedNum;
                if (mMyAdapter.selectedBean.get(i).selectedNum > z) {
                    mMyAdapter.selectedBean.get(i).selectedNum -= 1;
                }
            }
            dataBean.isSelected = false;
            dataBean.selectedNum = -1;
            mMyAdapter.selectedBean.remove(dataBean);
            mMyAdapter.notifyDataSetChanged();
        }
    

    ok,最后需要在MyAdapter中做判断

     @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof HeadViewHolder) {
                return;
            }
            if (holder instanceof BodyViewHolder) {
                setBodyViewHolder(((BodyViewHolder) holder), position);
            }
        }
    
        private void setBodyViewHolder(BodyViewHolder holder, final int position) {
            String path = mData.get(position - 1).filePath;
            DataBean dataBean = mData.get(position - 1);
            ImageUtil.getInstance().displayImage(mContext, path, holder.image, R.color.colorPrimary);//显示出图片
            if (dataBean.isSelected) {
    //            被选中的item就显示右上角的数字
                holder.tvNum.setVisibility(View.VISIBLE);
    //            注意这里需要加“”转化为String
                holder.tvNum.setText(dataBean.selectedNum + "");
            }
            holder.image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickListener != null) {
                        mOnItemClickListener.onItemClick(position);
                    }
                }
            });
        }
    

    终于完工了,总结一下,主要是对RecyclerView的应用,需要去设置一个透明的Head,然后就是图片数据的获取,最后填充到MyAdapter中。
    Just have a try.

    相关文章

      网友评论

          本文标题:RecyclerView显示系统所有图片表格排列并可选中大图显示

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