Android仿微信图片上传,相册多选及相关问题

前言

我们在做相册这块内容的时候,会发现调用android相册时,只能返回一张图片,而不是多张,所以需要我们自己重写一个相册,类似微信,微博等发布状态的需求!

仿微信图片上传界面

一般微信,微博等都是上传9张图片,而且都是九宫格形式展示,可以使用GridView或者GridLayout等实现。

下边主要讲一下RecyclerView的实现,借助此来记录一下RecyclerView子Item宽高正方形适配的方案!
先来张图吧!
Android仿微信图片上传,相册多选及相关问题_第1张图片
首先我们要在adapter子item布局,重新测量:

public class SquareItemLayout extends RelativeLayout {
    public SquareItemLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public SquareItemLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SquareItemLayout(Context context) {
        super(context);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        this.setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
        int childWidthSize = this.getMeasuredWidth();
        heightMeasureSpec = widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

然后在子item布局中作为父布局使用:


<xx.xxxx.xxxx.SquareItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/img_add"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="1dp"
        android:layout_gravity="center"
        android:scaleType="centerCrop"
        android:src="@mipmap/pic_add"
        android:adjustViewBounds="true"/>

    <ImageView
        android:id="@+id/img_del"
        android:clickable="true"
        android:paddingTop="2dp"
        android:paddingRight="2dp"
        android:paddingLeft="10dp"
        android:paddingBottom="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/img_add"
        android:layout_alignRight="@id/img_add"
        android:src="@mipmap/pic_del" />
xx.xxxx.xxxx.SquareItemLayout>

然后是我们的atapter,这个没有什么好说的,就是加载两种布局,一个添加图片的加号,一个是添加的图片,加号一直在最后

public class PhotoAdapter extends RecyclerView.Adapter {

    private ArrayList photoPaths = new ArrayList<>();
    private LayoutInflater inflater;

    private Context mContext;

    public final static int TYPE_ADD = 1;
    public final static int TYPE_PHOTO = 2;

    public final static int MAX = 9;

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    private OnItemClickListener mOnItemClickListener;

    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }

    public PhotoAdapter(Context mContext, ArrayList photoPaths) {
        this.photoPaths = photoPaths;
        this.mContext = mContext;
        inflater = LayoutInflater.from(mContext);

    }


    @Override public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = inflater.inflate(R.layout.layout_photo_item, parent, false);
        return new PhotoViewHolder(itemView);
    }


    @Override
    public void onBindViewHolder(final PhotoViewHolder holder,  int position) {

        if(mOnItemClickListener!=null){
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClick(v,holder.getAdapterPosition());
                }
            });
        }

        if (getItemViewType(position) == TYPE_PHOTO) {
            //图片
            //这里加上自己的图片加载逻辑
            }
            holder.ivPhoto_del.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

//删除图片
photoPaths.remove(holder.getAdapterPosition());
                    notifyDataSetChanged();
                }
            });
        }else{
            holder.ivPhoto_del.setVisibility(View.GONE);
        }
    }


    @Override 
    public int getItemCount() {
        int count = photoPaths.size() + 1;
        if (count > MAX) {
            count = MAX;
        }
        return count;
    }

    @Override
    public int getItemViewType(int position) {
        return (position == photoPaths.size() && position != MAX) ? TYPE_ADD : TYPE_PHOTO;
    }

    public static class PhotoViewHolder extends RecyclerView.ViewHolder {
        private ImageView ivPhoto;
        private ImageView ivPhoto_del;
        public PhotoViewHolder(View itemView) {
            super(itemView);
            ivPhoto   = (ImageView) itemView.findViewById(R.id.img_add);
            ivPhoto_del =(ImageView) itemView.findViewById(R.id.img_del);
        }
    }
}

最后在activity中的使用:

PhotoAdapter photoAdapter = new PhotoAdapter(getActivity(), pathList);
recyclerView.setLayoutManager(new GridLayoutManager(3, OrientationHelper.VERTICAL));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(photoAdapter);
photoAdapter.setOnItemClickListener(new PhotoAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                if (photoAdapter.getItemViewType(position) == PhotoAdapter.TYPE_ADD) {
                    //这里点击的是加号
                    //添加自己处理相册多选跳转的逻辑
                } else {
                    //这里点击的是图片
                    //添加自己处理图片点击事件逻辑
                }
            }
        });
    }

还有一个比较恶心的问题:就是选择GridLayoutManager的时候,这里我们想设置自己的间距。这里在网上找到一个,记录一下!

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {  

    private int spanCount;//跟LayoutManager参数一样 
    private int spacing;//自己想要设置的间距大小  
    private boolean includeEdge;//边缘是否设置间距  

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {  
        this.spanCount = spanCount;  
        this.spacing = spacing;  
        this.includeEdge = includeEdge;  
    }  

    @Override  
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {  
        int position = parent.getChildAdapterPosition(view); // item position  
        int column = position % spanCount; // item column  

        if (includeEdge) {  
            outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)  
            outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)  

            if (position < spanCount) { // top edge  
                outRect.top = spacing;  
            }  
            outRect.bottom = spacing; // item bottom  
        } else {  
            outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)  
            outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)  
            if (position >= spanCount) {  
                outRect.top = spacing; // item top  
            }  
        }  
    }  
}  

相册推荐开源项目

PhotoPicker
项目地址:https://github.com/donglua/PhotoPicker
Album
项目地址:https://github.com/yanzhenjie/Album

相册相关问题

拍照后系统图库不更新

我们经常会遇到这样的问题,就是调用相机拍完照以后,拍的图片会保存在我们指定的目录下,但是在系统相册中却看不到这一张图片。
怎么解决这个问题呢,就需要我们去通知系统相册去更新内容:
这块在PhotoPicker的示例demo中也有涉及到,这里单独拿出来说一下:

//调用相机拍照的Intent
public Intent dispatchTakePictureIntent(){
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
            // Create the File where the photo should go
            File file = createImageFile();
            Uri photoFile;
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                String authority = mContext.getApplicationInfo().packageName + ".provider";
                photoFile = FileProvider.getUriForFile(this.mContext.getApplicationContext(), authority, file);
            } else {
                photoFile = Uri.fromFile(file);
            }

            // Continue only if the File was successfully created
            if (photoFile != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
            }
        }
        return takePictureIntent;
    }

//通知相册更新内容
public void galleryAddPic() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        if (TextUtils.isEmpty(mCurrentPhotoPath)) {
            return;
        }
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        mContext.sendBroadcast(mediaScanIntent);
    }

这样我们在调用系统相机拍完照之后,系统的相册也会有拍完的照片!

优化查询大量本地图片

这块可以参考下面这篇文章,提供一个思路:
Android_优化查询加载大数量的本地相册图片

你可能感兴趣的:(Android学习笔记)