Android通过相册或拍照获取位图

实现:

1、在 xml 布局中实现一个图片布局

2、通过 button 控件弹框,让用户选择拍照还是从相册选择

3、得到位图,将位图按自己的需求处理(裁切成方形圆形)

4、在图片布局上显示位图 (有需要的还有可以保存位图、上传服务器)


效果:

界面显示


点击更改图像


在这里选择时拍照获取位图还是从相册选择


实现详情:

1、在 xml 布局中实现一个图片布局

简单的在需要的地方布局就好了,我 demo 的布局为:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center">
    <ImageView
        android:id="@+id/images"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:src="@mipmap/head"/>
</LinearLayout>
<Button
    android:id="@+id/change"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="更改图像"/>


2、通过 button 控件对话框,让用户选择拍照还是从相册选择

对话框的话,可以根据自己需要,自定义或者调用系统弹框都行

自定义弹框可以参照我的另一篇:android自定义对话框

http://blog.csdn.net/weixin_41454168/article/details/79538149

这里的话,我就用的系统对话框

change = (Button) findViewById(R.id.change);
change.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        //点击更改图像按钮后,就弹一个对话框,问:是拍照还是在相册中选?
        AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this)
                .setTitle("更改头像")
                .setMessage("请获取新的头像!")
                .setNegativeButton("拍照", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //调用摄像头拍照
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp_image.jpg"));
                        // 将拍照所得的相片保存到SD卡根目录
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                        startActivityForResult(intent, TAKE_PICTURE);
                    }
                })
                .setPositiveButton("相册", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        //调用相册、图库
                        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                        intent.setType("image/*");//选择图片
                        startActivityForResult(intent, CHOOSE_PICTURE);
                    }
                }).create();
        alertDialog.show();
    }
});

从源码中可以看到,无论是选择拍照还是相册,都会用 Intent 与系统通信,

从而调用系统相机或是系统图库


3、得到位图,将位图按自己的需求处理(裁切成方形圆形)

经过第二步后,拍照或是相册这些活动都会对系统都会有一个返回,

我们可以通过  onActivityResult(int requestCode, int resultCode, Intent data) 做出判断并处理:

//这里返回活动结果 (拍照或选择的图片)
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case TAKE_PICTURE:
                cutImage(uri); // 对图片进行裁剪处理
                break;
            case CHOOSE_PICTURE:
                cutImage(data.getData()); // 对图片进行裁剪处理
                break;
            case CROP_SMALL_PICTURE:
                if (data != null) {
                    setImageToView(data); // 让刚才选择裁剪得到的图片显示在界面上
                }
                break;
        }
    }
}

通过上面这个方法,判断出了用户进行了什么操作,

这时,如果这些操作有返回位图,就对这个位图进行处理(这里主要是裁剪位图:方形、圆形)

// 裁剪图片
protected void cutImage(Uri uri) {
    //调用系统自带的图片裁切功能(这里裁成正方形)
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    // 设置裁剪
    intent.putExtra("crop", "true");
    // aspectX aspectY 是宽高的比例
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    // outputX outputY 是裁剪图片宽高
    intent.putExtra("outputX", 150);
    intent.putExtra("outputY", 150);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, CROP_SMALL_PICTURE);
}

这时,位图已经是正方形了,如果有需要还可以裁切成圆形的(头像之类)

就需要定义一个方法来裁切,我把它写成了一个工具类:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;

/**
 * Created by Administrator on 2018/3/15 0015.
 * 将位图切割成圆形
 */

public class CircleUtils {
    //这个方法将位图切割成圆形
    public static Bitmap toRoundBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float roundPx;
        float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
        if (width <= height) {
            roundPx = width / 2;
            left = 0;
            top = 0;
            right = width;
            bottom = width;
            height = width;
            dst_left = 0;
            dst_top = 0;
            dst_right = width;
            dst_bottom = width;
        } else {
            roundPx = height / 2;
            float clip = (width - height) / 2;
            left = clip;
            right = width - clip;
            top = 0;
            bottom = height;
            width = height;
            dst_left = 0;
            dst_top = 0;
            dst_right = height;
            dst_bottom = height;
        }

        Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect src = new Rect((int) left, (int) top, (int) right,
                (int) bottom);
        final Rect dst = new Rect((int) dst_left, (int) dst_top,
                (int) dst_right, (int) dst_bottom);
        final RectF rectF = new RectF(dst);

        paint.setAntiAlias(true);

        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);

        canvas.drawCircle(roundPx, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, src, dst, paint);

        return output;
    }
}
如需要用到,直接调用就行了


4、在图片布局上显示位图 (有需要的还有可以保存位图、上传服务器)

将位图改成自己想要的样式之后,就可以显示在界面上去:

// 显示裁剪之后的图片数据
protected void setImageToView(Intent data) {
    Bundle extras = data.getExtras();
    if (extras != null) {
        try {
            bitmap = extras.getParcelable("data");

            //如果需要保存或上传没有切割成圆的位图,在这个位置应该可以(没试过)

            // 将位图处理成圆形(如果不加这行代码则显示正方形的图片)
            bitmap = CircleUtils.toRoundBitmap(bitmap);
            images.setImageBitmap(bitmap);

            //也可以在这里与服务器交互或保存位图

        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }
}

这里就是将 bitmap 通过 setImageBitmap() 方法放入布局中去如下

 images.setImageBitmap(bitmap); 


至于上传服务器或保存位图,就自己研究一下吧!


源码:https://github.com/iscopy/HeadPortrait









猜你喜欢

转载自blog.csdn.net/weixin_41454168/article/details/79568933