android选择图片从缩放到压缩再到圆形展示(一)

本文出自 “阿敏其人” 简书博客,转载或引用请注明出处。

我们要做的是从类似qq更换头像的功能。按下头像,弹出popup,通过拍照或者从相册选择图片,缩放,选择合适的大小,然后点击完成,更新头像。

一、先来简单地加载一张图片

先来看一下我们的默认图片.png

最简单的代码:

xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity"
    android:background="#ffffff"
    >

    <ImageView
        android:id="@+id/mIvPic"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:src="@mipmap/def_pic"

        />
</RelativeLayout>

.
.
MainActivity

public class MainActivity extends Activity {

    private ImageView mIvPic;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mIvPic = (ImageView) findViewById(R.id.mIvPic);

    }
}
像这样,最简单的图片就显示出来了.png

.
.

一、1 假如我们觉得矩形有点丑,想弄成圆角矩形怎么办呢?

我们知道,不管程序自带的图片,还是相册的图片,全部都是Bitmap。

既然要改变,我们就需要从Bitmap着手。

我们新建一个ImageTools类,添加一个方法,用于输出圆角(或者圆形)的bitmap

 */
public class ImageTools {

    /**
     *
     * 创建圆角图片
     * @param x 图像的宽度
     * @param y 图像的高度
     * @param image 源图片
     * @param outerRadiusRat 圆角的大小
     * @return 圆角图片
     */
    public static Bitmap createFramedPhoto(int x, int y, Bitmap image, float outerRadiusRat) {
        //根据源文件新建一个darwable对象
        Drawable imageDrawable = new BitmapDrawable(image);

        // 新建一个新的输出图片
        Bitmap output = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        // 新建一个矩形
        RectF outerRect = new RectF(0, 0, x, y);

        // 产生一个红色的圆角矩形
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED); 
        // 利用画笔画出一个矩形,第二个参数和第三个参数就是我们方法的传进来的圆角角度
        canvas.drawRoundRect(outerRect, outerRadiusRat, outerRadiusRat, paint);

        // 将源图片绘制到这个圆角矩形上
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        imageDrawable.setBounds(0, 0, x, y);
        canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG);
        imageDrawable.draw(canvas);
        canvas.restore();

        return output;
    }
}

.
.
然后在MainActivity里添加两行代码

public class MainActivity extends Activity {

    private ImageView mIvPic;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mIvPic = (ImageView) findViewById(R.id.mIvPic);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.def_pic);
        mIvPic.setImageBitmap(ImageTools.createFramedPhoto(80, 80, bitmap, 10));


    }
}

简单的圆角矩形呼之即出

圆角矩形.png

关于BitMmap的相关知识可以大概此文 安卓OOM和Bitmap图片二级缓存机制(一)

上面说了这么多,跟相册和头像没有毛线关系。那么现在,开始一点点关于相册和拍照的。

二、弹出Popup,选择相册或者拍照

思路是这样子:
点击图片的时候,我们弹出popupWindow,popup有三个选项
“拍照”
“相册”
“取消”

点击“拍照”和“相册”的时候,利用Intent调用系统的拍照和相册,使用
startActivityForResult的方式,传入一个请求码。

随后,在系统的onActivityResult方法里面针对不同的请求码做不同的操作。

开动:
既然要需要popup,首先就需要一个pop的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="20dp"
    android:paddingBottom="20dp"
    android:background="@drawable/shape_bg_pop"
    >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerInParent="true"

        >

        <TextView
            android:id="@+id/mTvPhoto"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp"
            android:background="@drawable/selector_pop_item"
            android:gravity="center"
            android:text="拍照"
            android:textColor="#0479FE"
            android:textSize="18sp" />



        <TextView
            android:id="@+id/mTvAlbum"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_above="@+id/cancel"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp"
            android:background="@drawable/selector_pop_item"
            android:gravity="center"
            android:text="从相册选择"
            android:textColor="#0479FE"
            android:layout_centerInParent="true"
            android:textSize="18sp"
            android:layout_marginTop="10dp"/>

        <TextView
            android:id="@+id/cancel"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:layout_alignParentBottom="true"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="40dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/selector_pop_item"
            android:gravity="center"
            android:text="取 消"
            android:textColor="#0479FE"
            android:textSize="18sp"
            >

        </TextView>

    </LinearLayout>
    
</RelativeLayout>
Popup的布局.png

关于PopupWindow的学习可以参考这里:android的PopupWindow简解

接下来可以正式写代码了


public class MainActivity extends Activity {

    private ImageView mIvPic;

    private PopupWindow popWindow;
    private LayoutInflater layoutInflater;

    private TextView mTvPhoto, mTvAlbum;
    private TextView cancel;

    public static final int PHOTOALBUMS = 0; // 相册
    public static final int PHOTOTAKE = 1; // 拍照
    public static final int IMAGE_COMPLETE = 2; // 结果

    private String photoSavePath;//保存文件夹路径
    private String photoSaveName;// 图片名称
    private String picFullPath;//图片全路径

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // 创建存放图片的文件夹
        File file = new File(Environment.getExternalStorageDirectory(), "ChoosePic/cache");

        SdCradUtils.createSDPath(file);

        // 这句代码不能少,因为我们的pop的点击事件有用到。
        photoSavePath=Environment.getExternalStorageDire
ctory()+"/ChoosePic/cache/";

        // 定义图片文件名
        photoSaveName =System.currentTimeMillis()+ ".png";

        mIvPic = (ImageView) findViewById(R.id.mIvPic);
//        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.def_pic);
//        mIvPic.setImageBitmap(ImageTools.createFramedPhoto(80, 80, bitmap, 10));

        mIvPic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showPopupWindow(mIvPic);
            }
        });
    }

    // 弹出Popup
    private void showPopupWindow(View parent){
        if (popWindow == null) {
            View view = layoutInflater.inflate(R.layout.pop_select_photo,null);
            popWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,true);
            initPop(view);
        }
        popWindow.setAnimationStyle(android.R.style.Animation_Toast);
        popWindow.setFocusable(true);
        popWindow.setOutsideTouchable(true);
        popWindow.setBackgroundDrawable(new BitmapDrawable());
        popWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        popWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);
    }

    // 初始化pop,对pop的选项进行操作
    public void initPop(View view){
        mTvPhoto = (TextView) view.findViewById(R.id.mTvPhoto);//拍照
        mTvAlbum = (TextView) view.findViewById(R.id.mTvAlbum);//相册
        cancel = (TextView) view.findViewById(R.id.cancel);//取消

        // 点击拍照
        mTvPhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {

                popWindow.dismiss();
                // 拍照后的图片的名字
                photoSaveName = String.valueOf(System.currentTimeMillis()) + ".png";
                Uri imageUri = null;
                // 调用系统相机
                Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                // 指定拍照后图片的存放路径和名称
                imageUri = Uri.fromFile(new File(photoSavePath, photoSaveName));
                openCameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
                openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                // 启动系统相机,Intent的请求码为PHOTOTAKE,用于在onActivityResult方法里面做相应操作
                startActivityForResult(openCameraIntent, PHOTOTAKE);
            }
        });

        // 点击相册
        mTvAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                popWindow.dismiss();

                // 4.4以上成功返回相册路径,并且向下兼容
                Intent openAlbumIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                openAlbumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(openAlbumIntent, PHOTOALBUMS);

            }
        });

        // 点击取消
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                popWindow.dismiss();

            }
        });
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Uri uri = null;
        switch (requestCode) {
            case PHOTOTAKE://拍照
                picFullPath=photoSavePath+photoSaveName;
                uri = Uri.fromFile(new File(picFullPath));
                System.out.println("拍照后得到的图片路径"+picFullPath);
                //简单粗暴地显示图片 (不好)
                Bitmap bitmap = BitmapFactory.decodeFile(picFullPath);
                mIvPic.setImageBitmap(bitmap);
                break;

            case PHOTOALBUMS://相册
                uri = data.getData();
                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();
                picFullPath = cursor.getString(column_index);// 图片在的路径
                //简单粗暴地显示图片 (不好)
                Bitmap bitmapAlbum = BitmapFactory.decodeFile(picFullPath);
                mIvPic.setImageBitmap(bitmapAlbum);
                System.out.println("调用相册后得到图片路径"+picFullPath);
                Log.d("qwe","xxxxxxxxx");
                break;
            default:
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

.
.
代码中我们还涉及到一个SD卡工具类

public class SdCradUtils {

    /**
     * 判断SDCard是否可用
     *
     * @return
     */
    public static boolean isSDCardEnable() {
        return Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);

    }

    /**
     * 根据传进来的File创建文件夹
     * 如果不存在,那么就创建
     * 如果已经存在该文件夹,那么不做任何操作(不会覆盖已存在的文件夹,不会影响旧文件夹已有的数据)
     * @param file
     */
    public static void createSDPath(File file) { //根据传来的路径创建sd卡

        if (isSDCardEnable()) {// 如果存在这个可以用的sd卡

            if (!file.exists()){
                file.mkdirs();
            }
        }

    }
}

在上面的代码中,我们在onCreate里面先创建了一个文件夹,即将拍照将另存在指定地址的图片指定了名称。

点击图片,弹出popup,相应的打开系统相机和相册几乎是模板代码。

最后,在onActivityResult里面根据请求码的不同,做相应的操作。

需要注意的是,按照我们上面的方式,我们拍照是以原图的方式存储到我们知道的位置,现在的手机像素都非常好,分辨率特别大,一般都是数千乘数千的的分辨率。这样不行,容易导致OOM.

所以像上面的代码虽然把大致的效果给弄出来了,但是这样要是在开发中绝对是不允许的。

所以接下来我们要对onActivityResult里面的代码进行完善:

拍照:得到原始的图片后,对图片进行压缩另存到我们知道的文件夹下,指定缩减至200k以下,然后加载压缩后的图片

相册:将相册选择好的图片压缩到200k以下(不动相册原有的图片),另存到我们指定的路径下,加载压缩后的图片

这里我们用到了两个工具类的方法:

关于压缩的:

    /**
     * 先按宽高比例大小缩小,再压缩为指定大小以下
     * 针对的是File
     * @param srcPath  图片路径
     * @param targetWidth  目标宽度
     * @param targetHeight  目标高度
     * @param targetKbSize  多少kb以下
     * @return
     */
    public static Bitmap decodeAndCompress(String srcPath,float targetWidth, float targetHeight,int targetKbSize) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片,此时把options.inJustDecodeBounds 设为true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空

        newOpts.inJustDecodeBounds = false;
        int startW= newOpts.outWidth;
        int startH = newOpts.outHeight;

        float targetH = targetHeight;//这里设置目标高度
        float targetW = targetWidth;//这里设置目标宽度
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        int squareRate = 1;//be=1表示不缩放,squareRate只能是整数大于1的整数,如果是2表示四分之一
        if (startW > startH && startW > targetW) {//如果宽度大的话根据宽度固定大小缩放
            squareRate = (int) (newOpts.outWidth / targetW);
        } else if (startW < startH && startH > targetH) {//如果高度高的话根据宽度固定大小缩放
            squareRate = (int) (newOpts.outHeight / targetH);
        }
        if (squareRate <= 0){
            squareRate = 1;
        }
        newOpts.inSampleSize = squareRate;//设置缩放比例
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);


        return compressQuality(bitmap,targetKbSize);//压缩好比例大小后再进行质量压缩
    }

    /**
     * 先让图片缩放到多少内存以下,接着缩放,最后压缩
     * 针对的是bitmap
     * 此方法对比decodeAndCompress最大的好处就是针对特别大的图片,一开始就先把大小限制在指定范围以下
     * @param image  bitmap
     * @param maxSize  界限,多少kb以下
     * @param targetWidth  目标宽
     * @param targetHeight 目标高
     * @param targetKbSize 最终压缩到多少kb以下
     * @return
     */

    public static Bitmap compressLimitDecodeCompress(Bitmap image,int maxSize,float targetWidth, float targetHeight,int targetKbSize) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        if( (baos.toByteArray().length / 1024)>maxSize) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片,此时把options.inJustDecodeBounds 设为了true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int startW = newOpts.outWidth;
        int startH = newOpts.outHeight;

        float targetW = targetWidth;
        float targetH = targetHeight;
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (startW > startH && startW > targetH) {//如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / targetH);
        } else if (startW < startH && startH > targetW) {//如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / targetW);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;//设置缩放比例
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565;//降低图片从ARGB888到RGB565
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
        isBm = new ByteArrayInputStream(baos.toByteArray());
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
        return compressQuality(bitmap,targetKbSize);//压缩好比例大小后再进行质量压缩
    }

   /**
     * 压缩图片质量到指定大小以下
     * @param bitmap
     * @param targetKbSize
     * @return
     */
    private static Bitmap compressQuality(Bitmap bitmap, int targetKbSize) {
        // 将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] b = baos.toByteArray();
        // 将字节换成KB
        double mid = b.length / 1024;
        // 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
        if (mid > targetKbSize) {
            // 获取bitmap大小 是允许最大大小的多少倍
            double i = mid / targetKbSize;
            // 开始压缩 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
            bitmap = zoomImage(bitmap, bitmap.getWidth() / Math.sqrt(i),
                    bitmap.getHeight() / Math.sqrt(i));
        }
        return bitmap;

    }

    public static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) {
        // 获取这个图片的宽和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 计算宽高缩放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放图片动作
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }


.
.
关于将Bitmap另存到sd卡的

    /**
     * 保存图片到sd卡片 亲测
     * @param mBitmap
     * @param path
     * @param picName
     */
    public static void saveBitmapToSdCard(Bitmap mBitmap,String path,String picName)  {
        File f = new File(path+picName + ".jpg");
        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
        try {
            fOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

.
.
附上完整代码,主要看onActivityResult

public class MainActivity extends Activity {

    private ImageView mIvPic;

    private PopupWindow popWindow;
    private LayoutInflater layoutInflater;

    private TextView mTvPhoto, mTvAlbum;
    private TextView cancel;

    public static final int PHOTOALBUMS = 0; // 相册
    public static final int PHOTOTAKE = 1; // 拍照
    public static final int IMAGE_COMPLETE = 2; // 结果

    private String photoSavePath;//保存文件夹路径
    private String photoSaveName;// 图片名称
    private String picFullPath;//图片全路径

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // 创建存放图片的文件夹
        File file = new File(Environment.getExternalStorageDirectory(), "ChoosePic/cache");

        SdCradUtils.createSDPath(file);
        // 这句代码不能少,因为我们的pop的点击事件有用到。
        photoSavePath=Environment.getExternalStorageDirectory()+"/ChoosePic/cache/";


        // 定义图片文件名
        photoSaveName =System.currentTimeMillis()+ ".png";

        mIvPic = (ImageView) findViewById(R.id.mIvPic);
//        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.def_pic);
//        mIvPic.setImageBitmap(ImageTools.createFramedPhoto(80, 80, bitmap, 10));

        mIvPic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showPopupWindow(mIvPic);
            }
        });




    }

    // 弹出Popup
    private void showPopupWindow(View parent){
        if (popWindow == null) {
            View view = layoutInflater.inflate(R.layout.pop_select_photo,null);
            popWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT,true);
            initPop(view);
        }
        popWindow.setAnimationStyle(android.R.style.Animation_Toast);
        popWindow.setFocusable(true);
        popWindow.setOutsideTouchable(true);
        popWindow.setBackgroundDrawable(new BitmapDrawable());
        popWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        popWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);
    }

    // 初始化pop,对pop的选项进行操作
    public void initPop(View view){
        mTvPhoto = (TextView) view.findViewById(R.id.mTvPhoto);//拍照
        mTvAlbum = (TextView) view.findViewById(R.id.mTvAlbum);//相册
        cancel = (TextView) view.findViewById(R.id.cancel);//取消

        // 点击拍照
        mTvPhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {

                popWindow.dismiss();
                // 拍照后的图片的名字
                photoSaveName = String.valueOf(System.currentTimeMillis()) + ".png";
                Uri imageUri = null;
                // 调用系统相机
                Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                // 指定拍照后图片的存放路径和名称
                imageUri = Uri.fromFile(new File(photoSavePath, photoSaveName));
                openCameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
                openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                // 启动系统相机,Intent的请求码为PHOTOTAKE,用于在onActivityResult方法里面做相应操作
                startActivityForResult(openCameraIntent, PHOTOTAKE);


            }
        });

        // 点击相册
        mTvAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                popWindow.dismiss();

                // 4.4以上成功返回相册路径,并且向下兼容
                Intent openAlbumIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                openAlbumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                startActivityForResult(openAlbumIntent, PHOTOALBUMS);

            }
        });

        // 点击取消
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                popWindow.dismiss();

            }
        });
    }



    @SuppressWarnings("deprecation")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        Uri uri = null;

        switch (requestCode) {

            case PHOTOTAKE://拍照
                picFullPath=photoSavePath+photoSaveName;
                uri = Uri.fromFile(new File(picFullPath));
                System.out.println("拍照后得到的图片路径"+picFullPath);

                //简单粗暴地显示图片 (不好)

                Bitmap bitmap = BitmapFactory.decodeFile(picFullPath);




                // 首先让图片变成1m以下,接着按照300*300的宽高去压缩,接着指定大小不超过200kb
                Bitmap bitmapCompress = CompressImageUtils.compressLimitDecodeCompress(bitmap, 1024, 300f, 300f, 200);
                ImageTools.saveBitmapToSdCard(bitmapCompress, photoSavePath, FileUtils.getFileName(picFullPath) + "compress");
                //SdCradUtils.deleteFile(picFullPath); //压缩之后删除照片

                mIvPic.setImageBitmap(bitmap);



                break;

            case PHOTOALBUMS://相册

                uri = data.getData();
                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();
                picFullPath = cursor.getString(column_index);// 图片在的路径


                //简单粗暴地显示图片 (不好)
                FileUtils.getFileOrFilesSize(picFullPath, 2); // 压缩前的图片大小
                Bitmap bitmapAlbum = BitmapFactory.decodeFile(picFullPath);

                // 首先让图片变成1m以下,接着按照300*300的宽高去压缩,接着指定大小不超过200kb
                Bitmap bmCompress = CompressImageUtils.compressLimitDecodeCompress(bitmapAlbum, 1024, 300f, 300f, 200);
                ImageTools.saveBitmapToSdCard(bmCompress, photoSavePath, FileUtils.getFileName(picFullPath) + "alb_compress");

                mIvPic.setImageBitmap(bmCompress);

                System.out.println("调用相册后得到图片路径" + picFullPath);

                break;


            default:
                break;
        }


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

实测之后我们发现,原本好几M的图片确实被压缩到200k以下了。

运行效果.png

提示:为了防止拍照后旋转手机,点击确定无法返回的问题
可以在清单文件的对应activity的添加
android:configChanges="orientation|keyboardHidden"
(屏幕横向纵向切换的问题)

展示图:

第一阶段gif.gif

下载链接

本篇完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容