1.创建一个Android Demo项目,设置拍照,读取等权限(基本的就不讲了,主要说明重点。)
2.创建自定义View
public class CropImageView extends View { // 在touch重要用到的点, private float mX_1 = 0; private float mY_1 = 0; // 触摸事件判断 private final int STATUS_SINGLE = 1; private final int STATUS_MULTI_START = 2; private final int STATUS_MULTI_TOUCHING = 3; // 当前状态 private int mStatus = STATUS_SINGLE; // 默认裁剪的宽高 private int cropWidth; private int cropHeight; // 浮层Drawable的四个点 private final int EDGE_LT = 1; private final int EDGE_RT = 2; private final int EDGE_LB = 3; private final int EDGE_RB = 4; private final int EDGE_MOVE_IN = 5; private final int EDGE_MOVE_OUT = 6; private final int EDGE_NONE = 7; public int currentEdge = EDGE_NONE; protected float oriRationWH = 0; protected final float maxZoomOut = 5.0f; protected final float minZoomIn = 0.333333f; protected Drawable mDrawable; protected FloatDrawable mFloatDrawable; protected Rect mDrawableSrc = new Rect();// 图片Rect变换时的Rect protected Rect mDrawableDst = new Rect();// 图片Rect protected Rect mDrawableFloat = new Rect();// 浮层的Rect protected boolean isFrist = true; private boolean isTouchInSquare = true; protected Context mContext; public CropImageView(Context context) { super(context); init(context); } public CropImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CropImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } @SuppressLint("NewApi") private void init(Context context) { this.mContext = context; try { if (android.os.Build.VERSION.SDK_INT >= 11) { this.setLayerType(LAYER_TYPE_SOFTWARE, null); } } catch (Exception e) { e.printStackTrace(); } mFloatDrawable = new FloatDrawable(context); } public void setDrawable(Drawable mDrawable, int cropWidth, int cropHeight) { this.mDrawable = mDrawable; this.cropWidth = cropWidth; this.cropHeight = cropHeight; this.isFrist = true; invalidate(); } @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { if (event.getPointerCount() > 1) { if (mStatus == STATUS_SINGLE) { mStatus = STATUS_MULTI_START; } else if (mStatus == STATUS_MULTI_START) { mStatus = STATUS_MULTI_TOUCHING; } } else { if (mStatus == STATUS_MULTI_START || mStatus == STATUS_MULTI_TOUCHING) { mX_1 = event.getX(); mY_1 = event.getY(); } mStatus = STATUS_SINGLE; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mX_1 = event.getX(); mY_1 = event.getY(); currentEdge = getTouch((int) mX_1, (int) mY_1); isTouchInSquare = mDrawableFloat.contains((int) event.getX(), (int) event.getY()); break; case MotionEvent.ACTION_UP: checkBounds(); break; case MotionEvent.ACTION_POINTER_UP: currentEdge = EDGE_NONE; break; case MotionEvent.ACTION_MOVE: if (mStatus == STATUS_MULTI_TOUCHING) { } else if (mStatus == STATUS_SINGLE) { int dx = (int) (event.getX() - mX_1); int dy = (int) (event.getY() - mY_1); mX_1 = event.getX(); mY_1 = event.getY(); // 根據得到的那一个角,并且变换Rect if (!(dx == 0 && dy == 0)) { switch (currentEdge) { case EDGE_LT: mDrawableFloat.set(mDrawableFloat.left + dx, mDrawableFloat.top + dy, mDrawableFloat.right, mDrawableFloat.bottom); break; case EDGE_RT: mDrawableFloat.set(mDrawableFloat.left, mDrawableFloat.top + dy, mDrawableFloat.right + dx, mDrawableFloat.bottom); break; case EDGE_LB: mDrawableFloat.set(mDrawableFloat.left + dx, mDrawableFloat.top, mDrawableFloat.right, mDrawableFloat.bottom + dy); break; case EDGE_RB: mDrawableFloat.set(mDrawableFloat.left, mDrawableFloat.top, mDrawableFloat.right + dx, mDrawableFloat.bottom + dy); break; case EDGE_MOVE_IN: if (isTouchInSquare) { mDrawableFloat.offset((int) dx, (int) dy); } break; case EDGE_MOVE_OUT: break; } mDrawableFloat.sort(); invalidate(); } } break; } return true; } // 根据初触摸点判断是触摸的Rect哪一个角 public int getTouch(int eventX, int eventY) { if (mFloatDrawable.getBounds().left <= eventX && eventX < (mFloatDrawable.getBounds().left + mFloatDrawable .getBorderWidth()) && mFloatDrawable.getBounds().top <= eventY && eventY < (mFloatDrawable.getBounds().top + mFloatDrawable .getBorderHeight())) { return EDGE_LT; } else if ((mFloatDrawable.getBounds().right - mFloatDrawable .getBorderWidth()) <= eventX && eventX < mFloatDrawable.getBounds().right && mFloatDrawable.getBounds().top <= eventY && eventY < (mFloatDrawable.getBounds().top + mFloatDrawable .getBorderHeight())) { return EDGE_RT; } else if (mFloatDrawable.getBounds().left <= eventX && eventX < (mFloatDrawable.getBounds().left + mFloatDrawable .getBorderWidth()) && (mFloatDrawable.getBounds().bottom - mFloatDrawable .getBorderHeight()) <= eventY && eventY < mFloatDrawable.getBounds().bottom) { return EDGE_LB; } else if ((mFloatDrawable.getBounds().right - mFloatDrawable .getBorderWidth()) <= eventX && eventX < mFloatDrawable.getBounds().right && (mFloatDrawable.getBounds().bottom - mFloatDrawable .getBorderHeight()) <= eventY && eventY < mFloatDrawable.getBounds().bottom) { return EDGE_RB; } else if (mFloatDrawable.getBounds().contains(eventX, eventY)) { return EDGE_MOVE_IN; } return EDGE_MOVE_OUT; } @Override protected void onDraw(Canvas canvas) { if (mDrawable == null) { return; } if (mDrawable.getIntrinsicWidth() == 0 || mDrawable.getIntrinsicHeight() == 0) { return; } configureBounds(); // 在画布上花图片 mDrawable.draw(canvas); canvas.save(); // 在画布上画浮层FloatDrawable,Region.Op.DIFFERENCE是表示Rect交集的补集 canvas.clipRect(mDrawableFloat, Region.Op.DIFFERENCE); // 在交集的补集上画上灰色用来区分 canvas.drawColor(Color.parseColor("#a0000000")); canvas.restore(); // 画浮层 mFloatDrawable.draw(canvas); } protected void configureBounds() { // configureBounds在onDraw方法中调用 // isFirst的目的是下面对mDrawableSrc和mDrawableFloat只初始化一次, // 之后的变化是根据touch事件来变化的,而不是每次执行重新对mDrawableSrc和mDrawableFloat进行设置 if (isFrist) { oriRationWH = ((float) mDrawable.getIntrinsicWidth()) / ((float) mDrawable.getIntrinsicHeight()); final float scale = mContext.getResources().getDisplayMetrics().density; int w = Math.min(getWidth(), (int) (mDrawable.getIntrinsicWidth() * scale + 0.5f)); int h = (int) (w / oriRationWH); int left = (getWidth() - w) / 2; int top = (getHeight() - h) / 2; int right = left + w; int bottom = top + h; mDrawableSrc.set(left, top, right, bottom); mDrawableDst.set(mDrawableSrc); int floatWidth = dipTopx(mContext, cropWidth); int floatHeight = dipTopx(mContext, cropHeight); if (floatWidth > getWidth()) { floatWidth = getWidth(); floatHeight = cropHeight * floatWidth / cropWidth; } if (floatHeight > getHeight()) { floatHeight = getHeight(); floatWidth = cropWidth * floatHeight / cropHeight; } int floatLeft = (getWidth() - floatWidth) / 2; int floatTop = (getHeight() - floatHeight) / 2; mDrawableFloat.set(floatLeft, floatTop, floatLeft + floatWidth, floatTop + floatHeight); isFrist = false; } mDrawable.setBounds(mDrawableDst); mFloatDrawable.setBounds(mDrawableFloat); } // 在up事件中调用了该方法,目的是检查是否把浮层拖出了屏幕 protected void checkBounds() { int newLeft = mDrawableFloat.left; int newTop = mDrawableFloat.top; boolean isChange = false; if (mDrawableFloat.left < getLeft()) { newLeft = getLeft(); isChange = true; } if (mDrawableFloat.top < getTop()) { newTop = getTop(); isChange = true; } if (mDrawableFloat.right > getRight()) { newLeft = getRight() - mDrawableFloat.width(); isChange = true; } if (mDrawableFloat.bottom > getBottom()) { newTop = getBottom() - mDrawableFloat.height(); isChange = true; } mDrawableFloat.offsetTo(newLeft, newTop); if (isChange) { invalidate(); } } // 进行图片的裁剪,所谓的裁剪就是根据Drawable的新的坐标在画布上创建一张新的图片 public Bitmap getCropImage() { Bitmap tmpBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565); Canvas canvas = new Canvas(tmpBitmap); mDrawable.draw(canvas); Matrix matrix = new Matrix(); float scale = (float) (mDrawableSrc.width()) / (float) (mDrawableDst.width()); matrix.postScale(scale, scale); Bitmap ret = Bitmap.createBitmap(tmpBitmap, mDrawableFloat.left, mDrawableFloat.top, mDrawableFloat.width(), mDrawableFloat.height(), matrix, true); tmpBitmap.recycle(); tmpBitmap = null; return ret; } public int dipTopx(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }
3. 创建XML文件,效果如图(样式不是很好看,主要实现功能就行)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginVertical="5dp" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="宽度:" /> <EditText android:id="@+id/width" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginHorizontal="5dp" android:inputType="number" android:singleLine="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="高度:" /> <EditText android:id="@+id/height" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginHorizontal="5dp" android:inputType="number" android:singleLine="true" /> <Button android:id="@+id/sure" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginHorizontal="5dp" android:text="确定" /> <Button android:id="@+id/crop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="裁剪" /> <Button android:id="@+id/save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginHorizontal="5dp" android:text="保存" /> <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消" /> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"> <com.example.cropphoto.util.CropImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageView android:id="@+id/image2" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> </LinearLayout>
4.创建裁剪框
public class FloatDrawable extends Drawable { private Context mContext; private int offset = 50; private Paint mLinePaint = new Paint(); private Paint mLinePaint2 = new Paint(); { mLinePaint.setARGB(200, 50, 50, 50); mLinePaint.setStrokeWidth(1F); mLinePaint.setStyle(Paint.Style.STROKE); mLinePaint.setAntiAlias(true); mLinePaint.setColor(Color.WHITE); // mLinePaint2.setARGB(200, 50, 50, 50); mLinePaint2.setStrokeWidth(7F); mLinePaint2.setStyle(Paint.Style.STROKE); mLinePaint2.setAntiAlias(true); mLinePaint2.setColor(Color.WHITE); } public FloatDrawable(Context context) { super(); this.mContext = context; } public int getBorderWidth() { return dipTopx(mContext, offset);//根据dip计算的像素值,做适配用的 } public int getBorderHeight() { return dipTopx(mContext, offset); } @Override public void draw(Canvas canvas) { int left = getBounds().left; int top = getBounds().top; int right = getBounds().right; int bottom = getBounds().bottom; Rect mRect = new Rect(left + dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2, right - dipTopx(mContext, offset) / 2, bottom - dipTopx(mContext, offset) / 2); //画默认的选择框 canvas.drawRect(mRect, mLinePaint); //画四个角的四个粗拐角、也就是八条粗线 canvas.drawLine((left + dipTopx(mContext, offset) / 2 - 3.5f), top + dipTopx(mContext, offset) / 2, left + dipTopx(mContext, offset) - 8f, top + dipTopx(mContext, offset) / 2, mLinePaint2); canvas.drawLine(left + dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2, left + dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2 + 30, mLinePaint2); canvas.drawLine(right - dipTopx(mContext, offset) + 8f, top + dipTopx(mContext, offset) / 2, right - dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2, mLinePaint2); canvas.drawLine(right - dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2 - 3.5f, right - dipTopx(mContext, offset) / 2, top + dipTopx(mContext, offset) / 2 + 30, mLinePaint2); canvas.drawLine((left + dipTopx(mContext, offset) / 2 - 3.5f), bottom - dipTopx(mContext, offset) / 2, left + dipTopx(mContext, offset) - 8f, bottom - dipTopx(mContext, offset) / 2, mLinePaint2); canvas.drawLine((left + dipTopx(mContext, offset) / 2), bottom - dipTopx(mContext, offset) / 2, (left + dipTopx(mContext, offset) / 2), bottom - dipTopx(mContext, offset) / 2 - 30f, mLinePaint2); canvas.drawLine((right - dipTopx(mContext, offset) + 8f), bottom - dipTopx(mContext, offset) / 2, right - dipTopx(mContext, offset) / 2, bottom - dipTopx(mContext, offset) / 2, mLinePaint2); canvas.drawLine((right - dipTopx(mContext, offset) / 2), bottom - dipTopx(mContext, offset) / 2 - 30f, right - dipTopx(mContext, offset) / 2, bottom - dipTopx(mContext, offset) / 2 + 3.5f, mLinePaint2); } @Override public void setBounds(Rect bounds) { super.setBounds(new Rect(bounds.left - dipTopx(mContext, offset) / 2, bounds.top - dipTopx(mContext, offset) / 2, bounds.right + dipTopx(mContext, offset) / 2, bounds.bottom + dipTopx(mContext, offset) / 2)); } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter cf) { } @SuppressLint("WrongConstant") @Override public int getOpacity() { return 0; } public int dipTopx(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }
5.创建Activity和Image工具类
public class ResizePhotoActivity extends AppCompatActivity implements View.OnClickListener { private EditText width; private EditText height; private Button sure, cancel, crop,save; private CropImageView imageView; private ImageUtils imageUtils; private ImageView image2; private Bitmap bitmap; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_resizephoto); imageView = findViewById(R.id.image); image2 = findViewById(R.id.image2); width = findViewById(R.id.width); height = findViewById(R.id.height); sure = findViewById(R.id.sure); sure.setOnClickListener(this); cancel = findViewById(R.id.btn_cancel); cancel.setOnClickListener(this); crop = findViewById(R.id.crop); crop.setOnClickListener(this); save = findViewById(R.id.save); save.setOnClickListener(this); // bitmap = BitmapFactory.decodeFile(ImageUtils.imgPathOri); // imageView.setDrawable(ImageUtils.imgPathOri); new Thread(new Runnable() { Drawable drawable = loadImage(ImageUtils.imgPathOri); @Override public void run() { imageView.post(new Runnable() { @Override public void run() { imageView.setDrawable(drawable, 200, 200); } }); } }).start(); } /** * 路径文件转资源文件 * * @param path * @return */ public Drawable loadImage(String path) { Drawable drawable = null; Bitmap bm = BitmapFactory.decodeFile(path); drawable = new BitmapDrawable(bm); if (drawable == null) { Log.d("test", "null drawable"); } else { Log.d("test", "not null drawable"); } return drawable; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.sure: if (width.getText().toString().equals("") && height.getText().toString().equals("")) { Toast.makeText(ResizePhotoActivity.this, "请输入裁剪宽高", Toast.LENGTH_SHORT).show(); } else { final int w = Integer.valueOf(width.getText().toString()); final int h = Integer.valueOf(height.getText().toString()); // Bitmap croppedImage = imageView.getCropImage(); new Thread(new Runnable() { Drawable drawable = new BitmapDrawable(ImageUtils.imgPathOri); @Override public void run() { imageView.post(new Runnable() { @Override public void run() { imageView.setDrawable(drawable, w, h); } }); } }).start(); } break; case R.id.btn_cancel: new Thread(new Runnable() { Drawable drawable = loadImage(ImageUtils.imgPathOri); @Override public void run() { imageView.post(new Runnable() { @Override public void run() { imageView.setDrawable(drawable, 200, 200); image2.setImageBitmap(null); } }); } }).start(); break; case R.id.crop: final Bitmap croppedImage = imageView.getCropImage(); new Thread(new Runnable() { @Override public void run() { imageView.post(new Runnable() { @Override public void run() { image2.setImageBitmap(croppedImage); } }); } }).start(); break; case R.id.save: ImageUtils imageUtils=new ImageUtils(ResizePhotoActivity.this); try { imageUtils.createCropImageFile(); } catch (IOException e) { e.printStackTrace(); } Bitmap bitmap = imageView.getCropImage(); System.out.println("---"+ImageUtils.imgPathCrop); try { FileOutputStream fos = new FileOutputStream(ImageUtils.imgPathCrop); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } this.finish(); } } }
public class ImageUtils { //原图像 路径 public static String imgPathOri; //裁剪图像 路径 public static String imgPathCrop; //原图像 URI public Uri imgUriOri; //裁剪图像 URI public Uri imgUriCrop; public PopupWindow popWinChoose; public static final String TAG = "ImageUtils"; public static final int REQUEST_OPEN_CAMERA = 0x011; public static final int REQUEST_OPEN_GALLERY = 0x022; public static final int REQUEST_CROP_PHOTO = 0x033; public static final int REQUEST_PERMISSIONS = 0x044; Activity activity; public ImageUtils(Activity activity) { this.activity = activity; } /** * ImageView设置优化内存使用后的Bitmap * 返回一个等同于ImageView宽高的bitmap * * @param view ImageView * @param imgPath 图像路径 */ public static void imageViewSetPic(ImageView view, String imgPath) { // Get the dimensions of the View int targetW = view.getWidth(); int targetH = view.getHeight(); // Get the dimensions of the bitmap BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(imgPath, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; // Determine how much to scale down the image int scaleFactor = Math.min(photoW / targetW, photoH / targetH); // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; Bitmap bitmap = BitmapFactory.decodeFile(imgPath, bmOptions); view.setImageBitmap(bitmap); } /** * 创建原图像保存的文件 * * @return * @throws IOException */ public File createOriImageFile() throws IOException { String imgNameOri = "HomePic_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File pictureDirOri = new File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/OriPicture"); if (!pictureDirOri.exists()) { pictureDirOri.mkdirs(); } File image = File.createTempFile( imgNameOri, /* prefix */ ".jpg", /* suffix */ pictureDirOri /* directory */ ); imgPathOri = image.getAbsolutePath(); return image; } /** * 创建裁剪图像保存的文件 * * @return * @throws IOException */ public File createCropImageFile() throws IOException { String imgNameCrop = "HomePic_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File pictureDirCrop = new File(activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/CropPicture"); if (!pictureDirCrop.exists()) { pictureDirCrop.mkdirs(); } File image = File.createTempFile( imgNameCrop, /* prefix */ ".jpg", /* suffix */ pictureDirCrop /* directory */ ); imgPathCrop = image.getAbsolutePath(); return image; } /** * 把图像添加进系统相册 * * @param imgPath 图像路径 */ public void addPicToGallery(String imgPath) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(imgPath); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); activity.sendBroadcast(mediaScanIntent); } public void setWindowAlpha(float alpha) { WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); lp.alpha = alpha; activity.getWindow().setAttributes(lp); } /** * 打开相机 * 7.0中如果需要调用系统(eg:裁剪)/其他应用,必须用FileProvider提供Content Uri,并且将Uri赋予读写的权限 */ public void openCamera() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 打开相机 File oriPhotoFile = null; try { oriPhotoFile = createOriImageFile(); } catch (IOException e) { e.printStackTrace(); } if (oriPhotoFile != null) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { imgUriOri = Uri.fromFile(oriPhotoFile); } else { imgUriOri = FileProvider.getUriForFile(this.activity, activity.getPackageName(), oriPhotoFile); } intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUriOri); activity.startActivityForResult(intent, REQUEST_OPEN_CAMERA); // 动态grant权限 // 如果在xml中已经定义android:grantUriPermissions="true" // 则只需要intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);即可 // List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); // for (ResolveInfo resolveInfo : resInfoList) { // String packageName = resolveInfo.activityInfo.packageName; // grantUriPermission(packageName, imgUriOri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); // } } } public void openGallery() { Intent intent = new Intent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { intent.setAction(Intent.ACTION_OPEN_DOCUMENT); } else { intent.setAction(Intent.ACTION_GET_CONTENT); // intent.setAction(Intent.ACTION_PICK); } intent.setType("image/*"); activity.startActivityForResult(intent, REQUEST_OPEN_GALLERY); } /** * 裁剪图片 * * @param uri 需要 裁剪图像的Uri */ public void cropPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); File cropPhotoFile = null; try { cropPhotoFile = createCropImageFile(); } catch (IOException e) { e.printStackTrace(); } if (cropPhotoFile != null) { // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { // imgUriCrop = Uri.fromFile(cropPhotoFile); // }else{ // imgUriCrop = FileProvider.getUriForFile(this.activity,activity.getPackageName(), cropPhotoFile); // } //7.0 安全机制下不允许保存裁剪后的图片 //所以仅仅将File Uri传入MediaStore.EXTRA_OUTPUT来保存裁剪后的图像 imgUriCrop = Uri.fromFile(cropPhotoFile); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", true); // intent.putExtra("aspectX", 100); // intent.putExtra("aspectY", 100); // intent.putExtra("outputX", w); // intent.putExtra("outputY", h); intent.putExtra("return-data", false); intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUriCrop); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); activity.startActivityForResult(intent, REQUEST_CROP_PHOTO); } } public void initChoosePop() { View view = LayoutInflater.from(activity).inflate(R.layout.popwin_sel, null); popWinChoose = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT); popWinChoose.setFocusable(true); // 设置popWindow弹出窗体可点击 popWinChoose.setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(R.color.transparent))); // popWinChoose.setAnimationStyle(R.style.storeImageChooseStyle); popWinChoose.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { setWindowAlpha(1); //Window设置为全透明 } }); TextView btnFirst = (TextView) view.findViewById(R.id.btn_first); TextView btnSecond = (TextView) view.findViewById(R.id.btn_second); TextView btnThird =(TextView) view.findViewById(R.id.btn_third); btnFirst.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openCamera(); popWinChoose.dismiss(); } }); btnSecond.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openGallery(); popWinChoose.dismiss(); } }); btnThird.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popWinChoose.dismiss(); } }); } }
流程:首先需要调用系统相机拍照,在OnActivityResult方法返回值时,跳转到自定义裁剪Activity,点击保存后回退主界面,调用OnResume方法获取裁剪后的url路径,加载显示即可。
效果如下图:
~~~~~~~~~~~~Over~~~~~~~~~~~~