手机相机和相册:基本调用与剪切相片

在Android系统中有很多系统控件是我们日常开发中经常使用到的,像键盘,相机,相册,电话,短信等等……今天道长给大家絮叨絮叨手机相册和相机的基本调用、系统自带的切图和自定义切图。让我们走起……

相机的基本调用

跳转到相机界面:

    private void startCamera(){
        String status = Environment.getExternalStorageState();
        if (status.equals(Environment.MEDIA_MOUNTED)) {// 判断是否有SD卡
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
                    Environment.getExternalStorageDirectory(), TMP_PATH)));
            startActivityForResult(intent, CAMERA_PICKED_WITH_DATA);
        } else {
            Toast.makeText(MainActivity.this, "没有SD卡",Toast.LENGTH_SHORT).show();
        }
    }


调用相机后返回的数据:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case CAMERA_PICKED_WITH_DATA:
                // 照相机程序返回的,再次调用图片剪辑程序去修剪图片
                picPath = Environment.getExternalStorageDirectory() + "/" + TMP_PATH;
                showPicture(null,picPath,doNext);
                break;
        }
    }

相册的基本调用

跳转到手机相册:

    private void startPhoto(){
        // 手机相册
        Intent intent = new Intent();
        // 开启Pictures画面Type设定为image
        intent.setType("image/*");
        // 使用Intent.ACTION_GET_CONTENT这个Action
        intent.setAction(Intent.ACTION_GET_CONTENT);
        // 取得相片后返回本画面
        startActivityForResult(intent, PHOTO_PICKED_WITH_DATA);
    }


调用相册后返回的数据:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case PHOTO_PICKED_WITH_DATA:
                Uri uri_ca = null;
                if (data != null && data.getData() != null) {
                    uri_ca = data.getData();
                } else {
                    if (photoUri != null) {
                        uri_ca = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri_ca);
                showPicture(uri_ca,picPath,doNext);
                break; 
        }
    }

剪切相片

剪切相片实际上是把相册中选中的相片或者从相机中返回的图片放到剪切界面,剪切后返回相片展示。剪切相片可以使用系统自带的,也可以自定义。系统自带的切图工具似乎只能剪切由相册返回的图片,由相机返回的图片不支持,道长功力不够(囧),没有找到合适的方法。希望有知道的童鞋可以告诉我一下,先谢谢了。自定义切图道长只是介绍最简单的切图,至于一些美图工具咱们不介绍。

系统切图工具

调用相机/相册获取先择的图片:

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_camera:
                doNext = "2show";
                startCamera();
                break;
            case R.id.btn_photo:
                doNext = "2show";
                startPhoto();
                break;
            case R.id.btn_system_cut_photo:
                doNext = "2system_cut";
                startPhoto();
                break;
        }
    }


相册返回的图片:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case PHOTO_PICKED_WITH_DATA:
                Uri uri_ca = null;
                if (data != null && data.getData() != null) {
                    uri_ca = data.getData();
                } else {
                    if (photoUri != null) {
                        uri_ca = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri_ca);
                showPicture(uri_ca,picPath,doNext);
                break;
        }
    }


系统切图工具返回的图片:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case PHOTO_PICKED_WITH_DATA:
                Uri uri_ca = null;
                if (data != null && data.getData() != null) {
                    uri_ca = data.getData();
                } else {
                    if (photoUri != null) {
                        uri_ca = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri_ca);
                showPicture(uri_ca,picPath,doNext);
                break;
            case CROP_RESULT_DATA:
                picPath = data.getStringExtra("crop_image_path");
                showPicture(null,picPath,"2show");
                break;
        }
    }

自定义剪切相片

调用相机/相册获取先择的图片:

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_camera_to_cut:
                doNext = "2custom_cut";
                startCamera();
                break;
            case R.id.btn_photo_to_cut:
                doNext = "2custom_cut";
                startPhoto();
                break;
        }
    }


相册/相机选择的图片

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case PHOTO_PICKED_WITH_DATA:
                Uri uri_ca = null;
                if (data != null && data.getData() != null) {
                    uri_ca = data.getData();
                } else {
                    if (photoUri != null) {
                        uri_ca = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri_ca);
                showPicture(uri_ca,picPath,doNext);
                break;
            case CAMERA_PICKED_WITH_DATA:

                // 照相机程序返回的,再次调用图片剪辑程序去修剪图片
                picPath = Environment.getExternalStorageDirectory() + "/" + TMP_PATH;
                showPicture(null,picPath,doNext);
                break;
            case CROP_RESULT_DATA:
                picPath = data.getStringExtra("crop_image_path");
                showPicture(null,picPath,"2show");
                break;
        }
    }

    private void showPicture(Uri uri,String filePath, String doNext){
        switch (doNext){
            case "2show":
                picFile = new File(filePath);
                picBitmap = PictureUtil.getBitmapThumbnail(picFile);
                picDrawable = new BitmapDrawable(picBitmap);
                if (picDrawable != null) {
                    iv_show.setImageDrawable(picDrawable);
                }
                break;
            case "2custom_cut":
                startCropImageActivity(filePath);
                break;
            case "2system_cut":
                startImageZoom(uri);
                break;
        }
    }


在上面的代码中相册和相机返回的相片,跳转到图片剪切界面,图片剪切界面实现:

public class ClipImageActivity extends Activity implements OnClickListener {
    public static String RESULT_PATH = "";
    private static final String KEY = "path";
    private ClipImageLayout mClipImageLayout = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.crop_image_layout);

        mClipImageLayout = (ClipImageLayout) findViewById(R.id.clipImageLayout);
        mClipImageLayout.setHorizontalPadding(100);// 设置剪切框padding值
        String path = getIntent().getStringExtra(KEY);

        // 有的系统返回的图片是旋转了,有的没有旋转,所以处理
        int degreee = readBitmapDegree(path);
        Bitmap bitmap = createBitmap(path);
        if (bitmap != null) {
            if (degreee == 0) {
                mClipImageLayout.setImageBitmap(bitmap);
            } else {
                mClipImageLayout.setImageBitmap(rotateBitmap(degreee, bitmap));
            }
        } else {
            finish();
        }
        findViewById(R.id.okBtn).setOnClickListener(this);
        findViewById(R.id.cancleBtn).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
            case R.id.okBtn:
                Bitmap bitmap = mClipImageLayout.clip();
                RESULT_PATH = System.currentTimeMillis() + "";
                String path = Environment.getExternalStorageDirectory() + "/"
                        + ClipImageActivity.RESULT_PATH + ".jpg";

                saveBitmap(bitmap, path);

                Intent intent = new Intent();
                intent.putExtra("crop_image_path", path);
                setResult(RESULT_OK, intent);
                this.finish();
                break;
            case R.id.cancleBtn:
                this.finish();
                break;
        }
    }

    public static void startActivity(Activity activity, String path, int code) {
        Intent intent = new Intent(activity, ClipImageActivity.class);
        intent.putExtra(KEY, path);
        activity.startActivityForResult(intent, code);
    }

    /**
     * 保存图片
     *
     * @param bitmap
     * @param path
     */
    private void saveBitmap(Bitmap bitmap, String path) {
        File f = new File(path);
        if (f.exists()) {
            f.delete();
        }

        FileOutputStream fOut = null;
        try {
            f.createNewFile();
            fOut = new FileOutputStream(f);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
            fOut.flush();
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            try {
                if (fOut != null)
                    fOut.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建图片
     *
     * @param path
     * @return
     */
    private Bitmap createBitmap(String path) {

        if (path == null) {
            return null;
        }

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = 1;
        opts.inJustDecodeBounds = false;
        opts.inPurgeable = true;
        opts.inInputShareable = true;
        opts.inDither = false;
        opts.inPurgeable = true;
        FileInputStream is = null;
        Bitmap bitmap = null;
        try {
            is = new FileInputStream(path);
            bitmap = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                    is = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return bitmap;
    }

    /**
     * 读取图像的旋转度
     *
     * @param path
     * @return
     */
    private int readBitmapDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋转图片
     *
     * @param angle
     * @param bitmap
     * @return
     */
    private Bitmap rotateBitmap(int angle, Bitmap bitmap) {
        // 旋转图片
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        return resizedBitmap;
    }
}

在这里道长自定义一个布局用来切割图片,但是这个方法并不是那么完美。经过道长实测能够实现切割,但是对于体量大的图片切割时,用户体验并不是那么好。下面我把实现贴上,希望有童鞋可以改进……

public class ClipImageLayout extends RelativeLayout {
    private ClipZoomImageView mZoomImageView;
    private ClipImageBorderView mClipImageView;

    public ClipImageLayout(Context context) {
        super(context);
        init();
    }

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

    public ClipImageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        // 浮点类型的计算器
//        floatEvaluator = new FloatEvaluator();
    }
    /**
     * 方法功能:获取子控件
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // 简单的异常处理
        if (getChildCount() != 2) {
            throw new IllegalArgumentException("SlideMenu only support 2 children!");
        }

        mClipImageView = (ClipImageBorderView) getChildAt(1);
        mZoomImageView = (ClipZoomImageView) getChildAt(0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        measureChild(mClipImageView, widthMeasureSpec, heightMeasureSpec);
        measureChild(mZoomImageView, widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = 0;
        int top = 0;

        mClipImageView.layout(left,top,mClipImageView.getMeasuredWidth(), mClipImageView.getMeasuredHeight());
        mZoomImageView.layout(left,top,mZoomImageView.getMeasuredWidth(), mZoomImageView.getMeasuredHeight());
    }


    public void setImageDrawable(Drawable drawable) {
        mZoomImageView.setImageDrawable(drawable);
    }

    public void setImageBitmap(Bitmap bitmap) {
        mZoomImageView.setImageBitmap(bitmap);
    }

    /**
     * 对外公布设置边距的方法 单位为dp
     *
     * @param mHorizontalPadding
     */
    public void setHorizontalPadding(int mHorizontalPadding) {
        mClipImageView.setHorizontalPadding(mHorizontalPadding);
        mZoomImageView.setHorizontalPadding(mHorizontalPadding);
    }

    /**
     * 裁切图片
     *
     * @return
     */
    public Bitmap clip() {
        return mZoomImageView.clip();
    }
}

至于其中涉及的代码就不一一贴出来了,如果有需要的话道长会把Demo贴到最后。

自定义切图返回的数据:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case PHOTO_PICKED_WITH_DATA:
                Uri uri_ca = null;
                if (data != null && data.getData() != null) {
                    uri_ca = data.getData();
                } else {
                    if (photoUri != null) {
                        uri_ca = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri_ca);
                showPicture(uri_ca,picPath,doNext);
                break;
            case CAMERA_PICKED_WITH_DATA:

                // 照相机程序返回的,再次调用图片剪辑程序去修剪图片
                picPath = Environment.getExternalStorageDirectory() + "/" + TMP_PATH;
                showPicture(null,picPath,doNext);
                break;
            case CROP_RESULT_DATA:
                picPath = data.getStringExtra("crop_image_path");
                showPicture(null,picPath,"2show");
                break;
            case CUSTOM_CROP_RESULT_DATA:

                Uri uri = null;
                if (data != null && data.getData() != null) {
                    uri = data.getData();
                } else {
                    if (photoUri != null) {
                        uri = photoUri;
                    } else {
                        return;
                    }
                }
                picPath = PictureUtil.getPath(this, uri);
                if (picPath == null) {
                    return;
                }
                showPicture(null,picPath,"2show");
                break;
        }

    }

到了这里,手机相机和相册的基本使用介绍完了,有不足的地方希望指正,希望这篇博客能为你提供一些帮助。

源码下载

CameraAndPhotoDemo


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值