手写一个修改头像的需求,头像图片支持手机拍照裁剪和从相册选择图片裁剪;
实现效果:
本节主要内容:
1)头像修改对话框实现;
2)调用系统相机拍照;
3)自定义图片裁剪页面;
4)从系统相册选择图片。
一、头像修改对话框实现
很简单的一个对话框
class HeadChangeDialog(context: Context) : Dialog(context, R.style.BottomDialog), View.OnClickListener {
var onHeadChangeListener: OnHeadChangeListener? = null
init {
this.init()
}
fun init() {
val contentView = LayoutInflater.from(context).inflate(R.layout.dialog_sdk_head_change, null)
setContentView(contentView)
val params = contentView.layoutParams as ViewGroup.MarginLayoutParams
params.width = context.resources.displayMetrics.widthPixels - DensityUtil.dp2px(context, 0f)
params.bottomMargin = DensityUtil.dp2px(context, 0f)
contentView.layoutParams = params
setCanceledOnTouchOutside(true)
window?.setGravity(Gravity.BOTTOM)
window?.setWindowAnimations(R.style.BottomDialog_Animation)
// 设置点击事件
contentView.findViewById<TextView>(R.id.tv_camera).setOnClickListener(this)
contentView.findViewById<TextView>(R.id.tv_photo).setOnClickListener(this)
contentView.findViewById<TextView>(R.id.tv_cancel).setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v!!.id) {
R.id.tv_camera -> {
onHeadChangeListener?.onCamera()
dismiss()
}
R.id.tv_photo -> {
onHeadChangeListener?.onPhoto()
dismiss()
}
R.id.tv_cancel -> dismiss()
}
}
interface OnHeadChangeListener {
fun onCamera()
fun onPhoto()
}
}
二、调用系统相机拍照
1)动态申请权限
private void toCamera() {
// 判断是否需要动态申请存储权限
if (!PermissionUtil.checksCameraPermission(this)) {
DialogManager.getInstance().showDialog(getString(R.string.camera_tip1), this, () -> {
if (PermissionUtil.deniedPermission()) {
// 用户已拒绝权限,跳转系统设置页
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
} else {
// 用户未拒绝权限,弹框动态申请权限
PermissionUtil.requestCameraPermission(this);
}
});
return;
}
startCamera();
}
2)调用系统相机拍照
在设置Uri是要注意,Android7.0及以上系统禁止应用向外部公开file://URI ,因此需要FileProvider来向外界传递URI。
public void takePicture(Activity activity, int requestCode) {
try {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (FileUtil.existSDCard()) {
takeImageFile = new File(Environment.getExternalStorageDirectory(), "/DCIM/camera/");
} else {
takeImageFile = Environment.getDataDirectory();
}
takeImageFile = createFile(takeImageFile, "IMG_", ".jpg");
if (takeImageFile != null) {
// 默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
// 照相机有自己默认的存储路径,拍摄的照片将返回一个缩略图。如果想访问原始图片,
// 可以通过dat extra能够得到原始图片位置。即,如果指定了目标uri,data就没有数据,
// 如果没有指定uri,则data就返回有数据!
Uri uri;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
uri = Uri.fromFile(takeImageFile);
} else {
/**
* 7.0 调用系统相机拍照不再允许使用Uri方式,应该替换为FileProvider
* 并且这样可以解决MIUI系统上拍照返回size为0的情况
*/
uri = FileProvider.getUriForFile(activity, ProviderUtil.getFileProviderName(activity), takeImageFile);
//加入uri权限 要不三星手机不能拍照
List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
activity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
LogUtil.i(TAG, ProviderUtil.getFileProviderName(activity));
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
activity.startActivityForResult(takePictureIntent, requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
3)自定义FileProvider
FileProvider是ContentProvider的一个子类,用于应用程序之间私有文件的传递。自Android 7.0后系统禁止应用向外部公开file://URI ,因此需要FileProvider来向外界传递URI,传递的形式是content : //Uri,使用时需要在清单文件中注册。
// 自定义一个Provider,以免和引入的项目的provider冲突
public class ImagePickerProvider extends FileProvider {
}
注册清单文件
<provider
android:name=".image.ImagePickerProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
创建provider_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
4)获取相机拍照图片路径,裁剪图片
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case ImagePicker.REQUEST_CODE_TAKE:
String imagePath = ImagePicker.getInstance().getTakeImageFile().getAbsolutePath();
LogUtil.i(TAG, "startCamera imagePath " + imagePath);
if (!TextUtils.isEmpty(imagePath)) {
Intent intent = new Intent(mContext, CorpImgActivity.class);
intent.putExtra(Constants.IMAGE_PATH, imagePath);
startActivityForResult(intent, ImagePicker.REQUEST_CODE_CROP);
}
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
三、自定义图片裁剪页面
图片裁剪页面功能实现:
1)显示图片
private void initData() {
Bundle bundle = getIntent().getExtras();
if (bundle != null && bundle.containsKey(Constants.IMAGE_URI)) {
Uri imageUri = (Uri) bundle.get(Constants.IMAGE_URI);
if (imageUri != null) {
try {
// 要裁剪的图片
mCropBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
mCorpImg.setImageBitmap(mCropBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
if (bundle != null && bundle.containsKey(Constants.IMAGE_PATH)) {
String imagePath = (String) bundle.get(Constants.IMAGE_PATH);
if (imagePath != null) {
try {
// 要裁剪的图片
mCropBitmap = BitmapFactory.decodeStream(new FileInputStream(imagePath));
// 旋转图片
int degree = BitmapUtil.getBitmapDegree(imagePath);
LogUtil.i(TAG, "degree " + degree);
if (degree != 0)
mCropBitmap = BitmapUtil.rotateBitmapByDegree(mCropBitmap, degree);
mCorpImg.setImageBitmap(mCropBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
2)实现拖拽图片
mCorpImg.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() ) {
case MotionEvent.ACTION_DOWN:
downX = motionEvent.getX();
downY = motionEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
Matrix matrix = mCorpImg.getImageMatrix();
//指定移动距离
matrix.postTranslate(motionEvent.getX() - downX, motionEvent.getY() - downY);
downX = motionEvent.getX();
downY = motionEvent.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
mCorpImg.invalidate();
return true;
}
});
3)放大缩小图片
mCorpImg.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & motionEvent.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
//次要点被点击
oldSpacing = spacing(motionEvent);
if (oldSpacing > 10f) {
isPointer = false;
isMain = false;
state = ZOOM;
midPoint(mid, motionEvent);
}
break;
case MotionEvent.ACTION_POINTER_UP:
//次要点松开
isPointer = true;
if (isPointer && isMain) {
isPointer = false;
isMain = false;
state = DRAG;
oldSpacing = 1f;
}
break;
case MotionEvent.ACTION_DOWN:
downX = motionEvent.getX();
downY = motionEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
Matrix matrix = mCorpImg.getImageMatrix();
if (state == DRAG) {
//拖拽
matrix.postTranslate(motionEvent.getX() - downX, motionEvent.getY() - downY);
downX = motionEvent.getX();
downY = motionEvent.getY();
} else if (state == ZOOM && !isPointer && !isMain) {
//放大缩小
float newSpacing = spacing(motionEvent);
float scale = newSpacing / oldSpacing;
matrix.postScale(scale, scale, mid.x, mid.y);
oldSpacing = newSpacing;
}
break;
case MotionEvent.ACTION_UP:
//用户多点触碰释放时,需要同时释放所有点才初始,防止发生偏移。
isMain = true;
if (isPointer && isMain) {
isPointer = false;
isMain = false;
state = DRAG;
oldSpacing = 1f;
}
break;
}
mCorpImg.invalidate();
return true;
}
});
/**
* 多点触控时,计算最先放下的两指距离
*
* @param event
* @return
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/**
* 多点触控时,计算最先放下的两指中心坐标
*
* @param point
* @param event
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
4)保存裁剪框区域图片
@Override
public void onRightTopMenuClick() {
super.onRightTopMenuClick();
Bitmap bitmap = getBitmap();
File file = FileUtil.createImageFile();
file = BitmapUtil.compressImage(bitmap, file);
mCropBitmap.recycle();
mCropBitmap = null;
Intent intent = new Intent();
intent.putExtra(Constants.IMAGE_PATH, file.getPath());
setResult(RESULT_OK, intent);
finish();
}
/**
* 获取裁剪框内截图
*
* @return
*/
private Bitmap getBitmap() {
// 获取截屏
mCropLayout.setDrawingCacheEnabled(true);
mCropLayout.buildDrawingCache();
// 计算裁剪框的开始位置
left = (mCropLayout.getWidth() - mCropView.getWidth()) / 2;
top = (mCropLayout.getHeight() - mCropView.getHeight()) / 2;
// 裁剪框的边框宽度
int borderWidth = DensityUtil.dp2px(getContext(), 2.5f);
Bitmap finalBitmap = Bitmap.createBitmap(mCropLayout.getDrawingCache(),
left + borderWidth, top + borderWidth, mCropView.getWidth() - 2 * borderWidth,
mCropView.getHeight() - 2 * borderWidth);
// 释放资源
mCropLayout.destroyDrawingCache();
return finalBitmap;
}
四、从系统相册选择图片
1)动态申请权限
private void toChooseImg() {
// 判断是否需要动态申请存储权限
if (!PermissionUtil.checksStoragePermission(this)) {
DialogManager.getInstance().showDialog(getString(R.string.storage_tip1), this, () -> {
if (PermissionUtil.deniedStoragePermission()) {
// 用户已拒绝权限,跳转系统设置页
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
} else {
// 用户未拒绝权限,弹框动态申请权限
PermissionUtil.requestStoragePermission(this);
}
});
return;
}
choosePhoto();
}
2)打开系统相册
public void photoAlbum(Activity activity, int requestCode) {
Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
// 单个图片类型:"image/jpeg 、 image/png等的类型",所有类型:"image/*"
intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
activity.startActivityForResult(intentToPickPic, requestCode);
}
3)获取获取手机相册图片Uri,裁剪图片
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case ImagePicker.REQUEST_CODE_PICK:
// 获取图片
try {
//该uri是上一个Activity返回的
Uri imageUri = data.getData();
LogUtil.i(TAG, "choosePhoto imageUri " + imageUri);
if (imageUri != null) {
Intent intent = new Intent(mContext, CorpImgActivity.class);
intent.putExtra(Constants.IMAGE_URI, imageUri);
startActivityForResult(intent, ImagePicker.REQUEST_CODE_CROP);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
功能完成,测试手机Android6.0、7.0及以上系统版本的华为、小米、三星、谷歌手机暂未发现问题。
源码:
图片选择工具类
package com.lib.common.image;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import androidx.core.content.FileProvider;
import com.lib.common.util.FileUtil;
import com.lib.common.util.LogUtil;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.text.SimpleDateFormat;
/**
* @Author: Jin
* @Description: 图片选择工具
* @CreateDate: 2023/4/20 14:50
*/
public class ImagePicker {
private static final String TAG = "ImagePicker";
public static final int REQUEST_CODE_TAKE = 1001; // 打开照相机
public static final int REQUEST_CODE_CROP = 1002; // 图片裁剪
public static final int REQUEST_CODE_PICK = 1003; // 打开相册
private File takeImageFile;
private static ImagePicker mInstance;
private ImagePicker() {
}
public static ImagePicker getInstance() {
if (mInstance == null) {
synchronized (ImagePicker.class) {
if (mInstance == null) {
mInstance = new ImagePicker();
}
}
}
return mInstance;
}
public File getTakeImageFile() {
return takeImageFile;
}
/**
* 拍照的方法
*/
public void takePicture(Activity activity, int requestCode) {
try {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (FileUtil.existSDCard()) {
takeImageFile = new File(Environment.getExternalStorageDirectory(), "/DCIM/camera/");
} else {
takeImageFile = Environment.getDataDirectory();
}
takeImageFile = createFile(takeImageFile, "IMG_", ".jpg");
if (takeImageFile != null) {
// 默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
// 照相机有自己默认的存储路径,拍摄的照片将返回一个缩略图。如果想访问原始图片,
// 可以通过dat extra能够得到原始图片位置。即,如果指定了目标uri,data就没有数据,
// 如果没有指定uri,则data就返回有数据!
Uri uri;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
uri = Uri.fromFile(takeImageFile);
} else {
/**
* 7.0 调用系统相机拍照不再允许使用Uri方式,应该替换为FileProvider
* 并且这样可以解决MIUI系统上拍照返回size为0的情况
*/
uri = FileProvider.getUriForFile(activity, ProviderUtil.getFileProviderName(activity), takeImageFile);
//加入uri权限 要不三星手机不能拍照
List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
activity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
LogUtil.i(TAG, ProviderUtil.getFileProviderName(activity));
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
activity.startActivityForResult(takePictureIntent, requestCode);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 根据系统时间、前缀、后缀产生一个文件
*/
public static File createFile(File folder, String prefix, String suffix) {
if (!folder.exists() || !folder.isDirectory()) folder.mkdirs();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA);
String filename = prefix + dateFormat.format(new Date(System.currentTimeMillis())) + suffix;
return new File(folder, filename);
}
/**
* 打开相册
*/
public void photoAlbum(Activity activity, int requestCode) {
Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
// 单个图片类型:"image/jpeg 、 image/png等的类型",所有类型:"image/*"
intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
activity.startActivityForResult(intentToPickPic, requestCode);
}
}
图片裁剪页面
package com.lib.common.image;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.lib.common.R;
import com.lib.common.constant.Constants;
import com.lib.common.ui.base.BaseActivity;
import com.lib.common.util.BitmapUtil;
import com.lib.common.util.DensityUtil;
import com.lib.common.util.FileUtil;
import com.lib.common.util.LogUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class CorpImgActivity extends BaseActivity implements View.OnTouchListener {
private static final String TAG = "CorpImgActivity";
private View mCropView;
private ImageView mCorpImg;
private RelativeLayout mCropLayout;
private Bitmap mCropBitmap;
private int top, left;
private float downX, downY;
private final int ZOOM = 1, DRAG = 0;
private float oldSpacing = 1f;
private int state;
/**
* 记录缩放时两指中间点坐标
*/
private PointF mid = new PointF();
private boolean isMain, isPointer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setActivityTitle(getString(R.string.crop_img));
setRightTopMenuShow(true);
setRightTopTitle(getString(R.string.save));
initView();
initData();
}
@Override
public int setLayoutId() {
return R.layout.activity_corp_img;
}
private void initView() {
mCropView = findViewById(R.id.crop_handler_select);
mCorpImg = findViewById(R.id.crop_handler_img);
mCropLayout = findViewById(R.id.crop_handler_layout);
//添加缩放功能
mCorpImg.setOnTouchListener(this);
}
private void initData() {
Bundle bundle = getIntent().getExtras();
if (bundle != null && bundle.containsKey(Constants.IMAGE_URI)) {
Uri imageUri = (Uri) bundle.get(Constants.IMAGE_URI);
if (imageUri != null) {
try {
// 要裁剪的图片
mCropBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
mCorpImg.setImageBitmap(mCropBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
if (bundle != null && bundle.containsKey(Constants.IMAGE_PATH)) {
String imagePath = (String) bundle.get(Constants.IMAGE_PATH);
if (imagePath != null) {
try {
// 要裁剪的图片
mCropBitmap = BitmapFactory.decodeStream(new FileInputStream(imagePath));
// 旋转图片
int degree = BitmapUtil.getBitmapDegree(imagePath);
LogUtil.i(TAG, "degree " + degree);
if (degree != 0)
mCropBitmap = BitmapUtil.rotateBitmapByDegree(mCropBitmap, degree);
mCorpImg.setImageBitmap(mCropBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & motionEvent.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
// 次要点被点击
oldSpacing = spacing(motionEvent);
if (oldSpacing > 10f) {
isPointer = false;
isMain = false;
state = ZOOM;
midPoint(mid, motionEvent);
}
break;
case MotionEvent.ACTION_POINTER_UP:
// 次要点松开
isPointer = true;
if (isPointer && isMain) {
isPointer = false;
isMain = false;
state = DRAG;
oldSpacing = 1f;
}
break;
case MotionEvent.ACTION_DOWN:
downX = motionEvent.getX();
downY = motionEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
Matrix matrix = mCorpImg.getImageMatrix();
if (state == DRAG) {
// 拖拽
matrix.postTranslate(motionEvent.getX() - downX, motionEvent.getY() - downY);
downX = motionEvent.getX();
downY = motionEvent.getY();
} else if (state == ZOOM && !isPointer && !isMain) {
// 放大缩小
float newSpacing = spacing(motionEvent);
float scale = newSpacing / oldSpacing;
matrix.postScale(scale, scale, mid.x, mid.y);
oldSpacing = newSpacing;
}
break;
case MotionEvent.ACTION_UP:
// 用户多点触碰释放时,需要同时释放所有点才初始,防止发生偏移。
isMain = true;
if (isPointer && isMain) {
isPointer = false;
isMain = false;
state = DRAG;
oldSpacing = 1f;
}
break;
}
mCorpImg.invalidate();
return true;
}
/**
* 多点触控时,计算最先放下的两指距离
*
* @param event
* @return
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/**
* 多点触控时,计算最先放下的两指中心坐标
*
* @param point
* @param event
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
int layoutWidth = mCropLayout.getWidth();
int layoutHeight = mCropLayout.getHeight();
int imgWidth = mCropBitmap.getWidth();
int imgHeight = mCropBitmap.getHeight();
int selectWidth = mCropView.getWidth();
int selectHeight = mCropView.getHeight();
float scaleNum; // 缩放比例
// 将要裁剪的图片长宽高做对比, 将较小的一方做等比缩放成裁剪框大小
if (imgWidth < imgHeight) {
scaleNum = (selectWidth * 1.0f) / (imgWidth * 1.0f);
imgHeight = (int) (scaleNum * imgHeight);
imgWidth = selectWidth;
} else {
scaleNum = (selectHeight * 1.0f) / (imgHeight * 1.0f);
imgWidth = (int) (scaleNum * imgWidth);
imgHeight = selectHeight;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleNum, scaleNum);
// 平移距离
matrix.postTranslate((layoutWidth - imgWidth) / 2, (layoutHeight - imgHeight) / 2);
// 设置缩放类型为 矩阵
mCorpImg.setScaleType(ImageView.ScaleType.MATRIX);
mCorpImg.setImageMatrix(matrix);
mCorpImg.setImageBitmap(mCropBitmap);
}
}
@Override
public void onRightTopMenuClick() {
super.onRightTopMenuClick();
Bitmap bitmap = getBitmap();
File file = FileUtil.createImageFile();
file = BitmapUtil.compressImage(bitmap, file);
mCropBitmap.recycle();
mCropBitmap = null;
Intent intent = new Intent();
intent.putExtra(Constants.IMAGE_PATH, file.getPath());
setResult(RESULT_OK, intent);
finish();
}
/**
* 获取裁剪框内截图
*
* @return
*/
private Bitmap getBitmap() {
// 获取截屏
mCropLayout.setDrawingCacheEnabled(true);
mCropLayout.buildDrawingCache();
// 计算裁剪框的开始位置
left = (mCropLayout.getWidth() - mCropView.getWidth()) / 2;
top = (mCropLayout.getHeight() - mCropView.getHeight()) / 2;
// 裁剪框的边框宽度
int borderWidth = DensityUtil.dp2px(getContext(), 2.5f);
Bitmap finalBitmap = Bitmap.createBitmap(mCropLayout.getDrawingCache(),
left + borderWidth, top + borderWidth, mCropView.getWidth() - 2 * borderWidth,
mCropView.getHeight() - 2 * borderWidth);
// 释放资源
mCropLayout.destroyDrawingCache();
return finalBitmap;
}
}
裁剪页面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@android:color/black"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/crop_handler_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/crop_handler_img"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="@+id/crop_handler_select"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="@drawable/bg_crop" />
</RelativeLayout>
</LinearLayout>