首页 > 代码库 > 从相机相册获取图片裁剪后用于评论晒图或更换背景图

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

这是我人生中写的第一篇博客,是否要纪念一下这一刻(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
<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

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