从相机相册获取图片裁剪后用于评论晒图或更换背景图

Posted 橘子焦糖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从相机相册获取图片裁剪后用于评论晒图或更换背景图相关的知识,希望对你有一定的参考价值。

这是我人生中写的第一篇博客,是否要纪念一下这一刻(2016.09.01 16:52)。其实关于写博客,老早就有这种写法,首先觉得他能够帮我总结我学到的和用过的技术,其次还能帮助那些和我有一样需求的人,我也是很开心啊,但是至于为什么现在才写第一篇,首先没有想好写什么,然后前段时间也确实比较忙。是不是那些来观技术的人已经想骂人了啊。。。啊哦!原谅我第一次写博客的激动心情吧!
废话不多说,开始我们的问题吧,首先因为我做了两次关于调用相机和相册获取图片的功能,觉得很有必要总结一下,下面我将从这两个功能出发完成这篇泊车

一、功能描述:

类似于淘宝评论中上传图片的功能先上图点击无裁剪无回显或有照相机的图片都可打开底部弹窗去获取图片

1.实现步骤:

①点击打开底部Dialog去选择拍照或者相册

/**
     * 1)打开底部弹窗
     * 
     * @author 陈静
     * @version 2016-9-1 下午5:21:21
     */
    private void openDialog() {
        mtakephoteDialog = new Dialog(this, R.style.my_dialog);
        LinearLayout view = (LinearLayout) LayoutInflater.from(
                MainActivity.this).inflate(R.layout.my_takephoto_dialog, null);
        TextView tp_dialog_tv = (TextView) view.findViewById(R.id.tp_dialog_tv);
        view.findViewById(R.id.tp_dialog_takebtn).setOnClickListener(
                MainActivity.this);
        view.findViewById(R.id.tp_dialog_picturebtn).setOnClickListener(
                MainActivity.this);
        view.findViewById(R.id.tp_dialog_canclebtn).setOnClickListener(
                MainActivity.this);
        tp_dialog_tv.setText("亲,你还可上传" + (2 - PHOTO_SUM) + "张照片");
        showBottomDialog(MainActivity.this, view, mtakephoteDialog);
    }

    /**
     * 2)显示底部弹窗
     */
    public final void showBottomDialog(Context context, View layout,
            Dialog myDialog) {
        // Dialog mCameraDialog = new Dialog(context, R.style.my_dialog);
        myDialog.setContentView(layout);
        Window dialogWindow = myDialog.getWindow();
        dialogWindow.setGravity(Gravity.BOTTOM);
        dialogWindow.setWindowAnimations(R.style.dialogstyle);// 添加动画
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();// 获取对话框当前的参数值
        lp.x = 0;// 新位置X坐标
        lp.y = -20;// 新位置Y坐标
        lp.width = (int) getResources().getDisplayMetrics().widthPixels;// 宽度//
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;// 高度
        lp.alpha = 9f;// 透明度
        layout.measure(0, 0);
        lp.height = layout.getMeasuredHeight();
        lp.alpha = 9f; // 透明度
        dialogWindow.setAttributes(lp);
        myDialog.show();
    }
    /**
     * 3)在styles.xml中配置弹窗样式
     *  */
   <style name="my_dialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <!-- 边框 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 是否浮现在activity之上 -->
        <item name="android:windowIsTranslucent">false</item>
        <!-- 半透明 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 无标题 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 背景透明 -->
        <item name="android:backgroundDimEnabled">true</item>
        <!-- 模糊 -->
    </style>
        <style name="dialogstyle" parent="android:Animation">
        <item name="@android:windowEnterAnimation">@anim/dialog_enter</item>
        <item name="@android:windowExitAnimation">@anim/dialog_exit</item>
   </style>
   /**
     * 4)在res下创建anim 文件夹,添加用到的两个动画
     *  */
    --- dialog_enter.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="400"
        android:fromYDelta="100%p" />
</set>
--- dialog_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="400"
        android:toYDelta="100%p" />
</set>

②点击打开相册或相机

1)点击打开相册
/*
* 从相册获取
*/
public void gallery() {
// 激活系统图库,选择一张图片
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_GALLERY
startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
}
2)点击打开相机
// 相机拍照方法
private void takeCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, PHOTO_REQUEST_CAREMA);

③获取到图片时接受相册或相机的返回图片,重写onActivityResult方法

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // 拍照返回
    String imagePath = new String();
    if (resultCode != Activity.RESULT_OK) {// result is not correct
        return;
    } else {
        if (requestCode == PHOTO_REQUEST_GALLERY) {
            // 从相册返回的数据
            if (data != null) {
                // 得到图片的全路径
                Uri uri = data.getData();
                // 展示图片
                if (PHOTO_SUM == 0) {
                    takephoto1.setVisibility(View.VISIBLE);
                    // 加载本地图片(路径以/开头, 绝对路径)
                    bitmapUtils.display(takephoto1,
                            getAbsoluteImagePath(uri));

                } else if (PHOTO_SUM == 1) {
                    takephoto2.setVisibility(View.VISIBLE);
                    evalute_takephoto_ib.setVisibility(View.GONE);
                    bitmapUtils.display(takephoto2,
                            getAbsoluteImagePath(uri));
                }
                PHOTO_SUM += 1;
                // 图片地址添加到集合中
                imagePath = getAbsoluteImagePath(uri);
                mFile.add(new File(imagePath));
            }

        } else if (requestCode == PHOTO_REQUEST_CAREMA) {
            // 根据有没有SD卡给出相关路径
            String picName = "evalute" + System.currentTimeMillis()
                    + ".png";
            String picPath = new String();
            if (hasSdcard()) {
                picPath = Environment.getExternalStorageDirectory()
                        .toString();
                imagePath = picPath + "/" + picName;
            } else {
                picPath = this.getFilesDir().toString();
                imagePath = picPath + "/" + picName;
            }
            // 得到图片的全路径
            Bitmap bitmap = data.getParcelableExtra("data");
            saveBitmap(picPath, picName, bitmap);// 图片保存到本地
            mFile.add(new File(imagePath));// 保存路径添加到集合中
            // 在界面上展示对应图片
            if (PHOTO_SUM == 0) {
                takephoto1.setVisibility(View.VISIBLE);
                this.takephoto1.setImageBitmap(bitmap);
            } else if (PHOTO_SUM == 1) {
                takephoto2.setVisibility(View.VISIBLE);
                evalute_takephoto_ib.setVisibility(View.GONE);
                this.takephoto2.setImageBitmap(bitmap);
            }
            PHOTO_SUM += 1;
        }
    }
    // 关闭底部弹窗
    if (mtakephoteDialog != null) {
        mtakephoteDialog.dismiss();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

④提供这其中用到的几个方法

/**
     * 将Uri转换为绝对路径
     * 
     * @author 陈静
     * @version 2016-7-29 下午2:50:18
     */
    protected String getAbsoluteImagePath(Uri uri) {
        // can post image
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, proj, null, null, null);

        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    /**
     * 将拍摄的图片保存到本地
     * 
     * @author 陈静
     * @version 2016-7-29 下午2:50:53
     */
    public void saveBitmap(String picPath, String picName, Bitmap bm) {

        File f = new File(picPath, picName);
        if (f.exists()) {
            f.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            bm.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
     * 判断sdcard是否被挂载
     */
    private boolean hasSdcard() {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            return true;
        } else {
            return false;
        }
    }

2.温馨提示

①此界面显示图片用到了Xutils的bitmaputils
②在此功能中添加private List<File> mFile = new ArrayList<File>();// 把图片保存到file数组中用于循环上传到服务器

二、功能描述:

类似于微信朋友圈点击更换背景图片的功能,即:点击图片后弹窗提示更换背景图片,点击后跳转页面,去选择拍照还是从相册获取,并进行裁剪后返回到上一个页面,这里也上张图吧点击有裁剪有回显或下面大图可弹出更换提示框

1.实现步骤:

①点击弹出popuwindow提示更换背景图片

    // 弹出更换背景图片的popuwindow
private void changBGPopuwindow() {
    // 1.加载布局
    View mView = View.inflate(MainActivity.this,
            R.layout.change_userinfo_bg, null);
    pm = new PopupWindow(mView, LayoutParams.MATCH_PARENT,
            LayoutParams.WRAP_CONTENT, true);
    // 如果不添加这行代码,点击pw区域之外的地方不能关闭pw
    pm.setBackgroundDrawable(new ColorDrawable());

    // pm.showAsDropDown(cic_part1_0_rl,0,-cic_part1_0_rl.getHeight());
    pm.showAtLocation(rl, Gravity.CENTER, 0, 150);
}

②点击更换背景图片的跳转选择相机或拍照的页面

// 点击更换背景图片的Poupuwindow
public void changUsesBg(View v) {
    pm.dismiss();
    Intent intent = new Intent();
    intent.setClass(MainActivity.this, ChangeBGActivity.class);
    startActivityForResult(intent, 777);

}  

③ 点击相机或拍照

  // 相机拍照方法
    private void takeCamera() {
        // Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // startActivityForResult(cameraIntent, PHOTO_REQUEST_CAREMA);
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        boolean sdCardExist = Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
        if (sdCardExist == true) {
            imageUri = Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory(), picName));
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(cameraIntent, PHOTO_REQUEST_CAREMA);
        } else {
            imageUri = Uri.fromFile(new File(ChangeBGActivity.this
                    .getFilesDir(), picName));
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(cameraIntent, PHOTO_REQUEST_CAREMA);
        }
    }
    /*
     * 从相册获取
     */
    public void gallery() {
        // 激活系统图库,选择一张图片
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_GALLERY
        startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
    }

④重写onActivityResult方法接收相机或相册传回来的图片,然后调用裁剪的方法得到最终图片后传递到上一个界面

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        String imagePath = new String();
        if (resultCode != Activity.RESULT_OK) {// result is not correct
            return;
        } else {
            if (requestCode == PHOTO_REQUEST_GALLERY) {
                // 从相册返回的数据
                if (data != null) {
                    // 得到图片的全路径
                    Uri uri = data.getData();
                    // 裁剪图片
                    crop(uri);
                    // 图片地址添加到集合中
                    imagePath = getAbsoluteImagePath(uri);
                    mFile.add(new File(imagePath));
                }
            } else if (requestCode == PHOTO_REQUEST_CAREMA) {
                // 根据有没有SD卡给出相关路径
                String picPath = new String();
                if (hasSdcard()) {
                    picPath = Environment.getExternalStorageDirectory()
                            .toString();
                    imagePath = picPath + "/" + picName;
                } else {
                    picPath = this.getFilesDir().toString();
                    imagePath = picPath + "/" + picName;
                }
                // 裁剪图片
                crop(Uri.fromFile(new File(imagePath)));
                // 得到图片的全路径
                // Bitmap bitmap = data.getParcelableExtra("data");
                // saveBitmap(picPath, picName, bitmap);// 图片保存到本地
                // mFile.add(new File(imagePath));// 保存路径添加到集合中
                // 在界面上展示对应图片
            } else if (requestCode == PHOTO_REQUEST_CUT) {
                // 从剪切图片返回的数据
                if (data != null) {
                    Bitmap bitmap = data.getParcelableExtra("data");

                    Intent intent = getIntent();
                    intent.putExtra("bitmap", bitmap);
                    setResult(666, intent);
                    finish();
                }
                try {
                    // 将临时文件删除
                    // tempFile.delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

⑤调用裁剪的方法

// 剪切图片
    private void crop(Uri uri) {
        // 裁剪图片意图
        // Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");// 裁剪框的比例,1:1
        intent.putExtra("scale", true);// 去黑边
        intent.putExtra("aspectX", 11);
        intent.putExtra("aspectY", 8); // 裁剪后输出图片的尺寸大小
        intent.putExtra("outputX", 220);
        intent.putExtra("outputY", 160);
        intent.putExtra("outputFormat", "PNG");// 图片格式
        intent.putExtra("noFaceDetection", true);// 取消人脸识别
        intent.putExtra("return-data", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
        // 设置剪切的图片保存位置
        Uri cropUri = null;
        if (hasSdcard()) {
            cropUri = Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory(), "bg_crop.png"));
        } else {
            cropUri = Uri.fromFile(new File(ChangeBGActivity.this
                    .getFilesDir(), "bg_crop.png"));
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CUT
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
    }

⑥在上一个界面接受传递过来的图片并显示

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // changBgActivity返回的数据
        if (resultCode == 666) {
            Bitmap bitmap = data.getParcelableExtra("bitmap");
            BitmapDrawable bd = new BitmapDrawable(bitmap);
            rl.setBackgroundDrawable(bd);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

⑦在界面下一次打开时,回显该图片

// 判断有没有背景图片
        Uri cropUri = null;
        if (hasSdcard()) {
            cropUri = Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory(), "bg_crop.png"));
        } else {
            cropUri = Uri.fromFile(new File(MainActivity.this.getFilesDir(),
                    "bg_crop.png"));
        }
        rl.setBackgroundDrawable(Drawable.createFromPath(cropUri.getPath()));
    }

2.温馨提示:

①此功能中用到的一些方法已在功能已中提供,不在细列
②输出的图片有2种情况:
1)如果你没有指定Intent里面的Extra参数,它就返回一个序列化(putExtra(“data”, bitmap))的Bitmap(参照1. 获得拍照的预览图)。
2)如果你指定了Intent里面的Extra参数MediaStore.EXTRA_OUTPUT,拍照后它就直接把bitmap写到了Uri里面了,返回是空

结语:

至此,我的第一篇博客结束了,可能表达的不是很清楚,但希望能够对需要的人有所帮助,为了能让大家更方便我单独整理除了一个Demo(eclipse),供大家参考,喜欢的话,就鼓励我吧,以后我就会更愿意分享更多的东西了
下载源码:http://download.csdn.net/detail/qq_25283953/9619905

以上是关于从相机相册获取图片裁剪后用于评论晒图或更换背景图的主要内容,如果未能解决你的问题,请参考以下文章

Android--利用相机或相册截取用户头像(解决了miui无法截取,以及部分机型拍照无返回Uri)

Android中通过访问本地相册或者相机设置用户头像

APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能

APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能

APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能

APP开发-使用Vue3+vant+html5+ 实现相机拍照,选取相册图片,裁剪图片以及提取图片中的文字等功能