android多图选择器demo

来源:互联网 发布:上瘾网络剧全集 编辑:程序博客网 时间:2024/05/17 04:42

本文是根据鸿祥大神的博客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 0