android多图选择器demo

本文是根据鸿祥大神的博客http://blog.csdn.net/lmj623565791/article/details/39943731进化而来,在大神的基础上更进一步封装拍照,防止oom,选择图片后回调。

效果如图所示,点击加号弹出dialog,可以选择从照相机拍照也可以选择从图库选择多张图片。

为了方变使用,封装了一个父类。在父类中进行dialog的点击事件响应并接收照相机的回调和多图选择后的回调,并对外提供两个接口,一个是选择单一图片的回调,一个是选择多图的回调。代码如下

public class SelectImageActivity extends AppCompatActivity{

    protected CameraAlbumDialog mCameraDialog;
    private Uri mUri;
    //相机回调参数,
    public static final int REQ_CAMERA = 0x01;
    //系统图库参数
    public static final int REQ_ALBUM = 0x02;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initCameraDialog();
    }

    public void initCameraDialog(){
        mCameraDialog = new CameraAlbumDialog(this);
        mCameraDialog.getWindow().setGravity(Gravity.BOTTOM);
        // 拍照
        mCameraDialog.setOnCameraClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadRealImgFromCamera();
                mCameraDialog.dismiss();
            }
        });
        // 相册
        mCameraDialog.setOnAlbumClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadImgFromAlbum();
                mCameraDialog.dismiss();
            }
        });
        // 取消
        mCameraDialog.setOnCancleClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCameraDialog.dismiss();
            }
        });
    }

    /**
     * 跳转到另一个页面进行多图操作
     */
    private void loadImgFromAlbum() {
        Intent openAlbumIntent = new Intent(this, OpenAlbumActivity.class);
        startActivityForResult(openAlbumIntent,REQ_ALBUM);
    }

    /**
     * 打开照相机
     */
    private void loadRealImgFromCamera() {
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (mUri == null) {
            mUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "cameraImghead.jpg"));
        }
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
        startActivityForResult(cameraIntent, REQ_CAMERA);
    }

    /**
     * 相机回调和多图回调
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQ_CAMERA && resultCode == -1) {
            jiantu(mUri);
        } else if (requestCode == 3 && resultCode == -1) {
            if (mUri != null&&listener!=null) {
                listener.getImgUrl(mUri);
            }
        }else if (requestCode == REQ_ALBUM&&resultCode == -1){
            if (listener!=null){
                listener.getImgUrl(data.getStringArrayListExtra("urls"));
            }
        }
    }



    /**
     * 拍照剪裁
     */
    private void jiantu(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("scale", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        intent.putExtra("return-data", false);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true); // no face detection
        startActivityForResult(intent, 3);
    }

    public interface imgUrlListener{
        void getImgUrl(Uri url); //返回一张图片的地址
        void getImgUrl(ArrayList<String> urls); //返回一组图片的地址
    }

    imgUrlListener listener;

    public void setListener(imgUrlListener listener) {
        this.listener = listener;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCameraDialog = null;
    }
在MainActivity里面进行进行监听图片选择后的监听回调,并在GridView里面进行显示代码如下,要注意权限,Android6.0应该在代码了主动调用获取相机授权。
        mGridView = (GridView)findViewById(R.id.grid_photo);
        mData = new ArrayList<>();
        mAdapter = new GridPhotoAdapter(this,mData);
        mGridView.setAdapter(mAdapter);

        /**
         * 监听项目需求最多选择6张图,不到6张就显示加号,选到6张就隐藏掉加号
         */
        setListener(new imgUrlListener() {
            @Override
            public void getImgUrl(Uri url) {
                mData.add(url.toString());
                mAdapter.notifyDataSetChanged();
            }

            @Override
            public void getImgUrl(ArrayList<String> urls) {
                for (int i = 0; i < urls.size(); i++) {
                    if (mData.size() < 6) {
                        mData.add(urls.get(i));
                    }
                }
                mAdapter.notifyDataSetChanged();
            }
        });

        /**
         * 当点击的位置等于图片数组的长度时,可以知道此时图片数小于6张,并且点击的是加号,显示选择图片的dialog
         */
        mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                if (i == mData.size()) {
                    mCameraDialog.show();
                }
            }
        });
    }


因为需要显示加号而且需求是最多显示6张图片,所以要在adapter里面要进行逻辑上的操作

private Context mContext;
    private List<String> mData;

    public GridPhotoAdapter(Context context, List<String> data){
        mContext = context;
        mData = data;
    }

    @Override
    public int getCount() {
        if (mData.size()<6){
            return mData.size()+1;
        }else{
            return mData.size();
        }
    }

    @Override
    public Object getItem(int i) {
        return mData.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        viewHolder holder;
        if (view == null){
            view = LayoutInflater.from(mContext).inflate(R.layout.item_photo,null);
            holder = new viewHolder();
            holder.simpleDraweeView = (ImageView) view.findViewById(R.id.image);
            holder.ivAdd = (ImageView) view.findViewById(R.id.iv_add);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams((int) ScreenUtils.getScreenWidth(mContext)/3-20,(int)ScreenUtils.getScreenWidth(mContext)/3-20);
            holder.simpleDraweeView.setLayoutParams(lp);
            view.setTag(holder);
        }else{
            holder = (viewHolder) view.getTag();
        }
        if (mData.size() <= 6){
            if (i < mData.size()){
                holder.ivAdd.setVisibility(View.GONE);
                if (mData.get(i).contains("file:///")){
                    ImageLoader.getInstance(3, ImageLoader.Type.LIFO).loadImage(mData.get(i).substring(7), holder.simpleDraweeView);
                }else{
                    ImageLoader.getInstance(3, ImageLoader.Type.LIFO).loadImage(mData.get(i), holder.simpleDraweeView);
                }
            }else{
                holder.ivAdd.setVisibility(View.VISIBLE);
                ImageLoader.getInstance(3, ImageLoader.Type.LIFO).loadImage("", holder.simpleDraweeView);
            }
        }
        return view;
    }

    class viewHolder{
        ImageView simpleDraweeView;
        ImageView ivAdd;
    }

    public void onDestory(){
        mContext = null;
        mData = null;
    }
要注意调用相机返回的url地址和调用多图选择返回的url地址不一样,相机回调产生的地址前部分含有“file///”所以判断当含有这个字符串时要进行截取。然后显示。

为了防止oom,在ImageLoder里面将图片的宽高根据比例压缩后,再度压缩2倍

/**
	 * 计算inSampleSize,用于压缩图片
	 * 
	 * @param options
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */
	private int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight)
	{
		// 源图片的宽度
		int width = options.outWidth;
		int height = options.outHeight;
		int inSampleSize = 1;

		if (width > reqWidth && height > reqHeight)
		{
			// 计算出实际宽度和目标宽度的比率
			int widthRatio = Math.round((float) width / (float) reqWidth);
			int heightRatio = Math.round((float) width / (float) reqWidth);
			inSampleSize = Math.max(widthRatio*2, heightRatio*2);
		}
		return inSampleSize;
	}
源码已上传地址在http://download.csdn.net/detail/u013692888/9758445

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值