• Android 自定义截图,可设置裁剪框宽高


    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~~~~~~~~~~~~

    本文来自博客园,作者:Forever丶随风,转载请注明原文链接:https://www.cnblogs.com/Forever-wind/p/14955478.html

  • 相关阅读:
    Spring中这么重要的AnnotationAwareAspectJAutoProxyCreator类是干嘛的?
    Spring到底应该学哪些内容?
    如何评价《Java 并发编程艺术》这本书?
    在腾讯工作是一种怎样的体验?
    图解 HTTP 连接管理
    42 张图带你撸完 MySQL 优化
    我是如何进入腾讯的?
    《计算机网络 PDF》搞起!
    JSR
    RelationNet:学习目标间关系来增强特征以及去除NMS | CVPR 2018
  • 原文地址:https://www.cnblogs.com/Forever-wind/p/14955478.html
Copyright © 2020-2023  润新知