如何像Facebook个人资料图像选择工具那样移动和缩放图像?

Chi*_*rag 5 android image crop

我希望裁剪图像像Android上的Facebook个人资料图像选择,用户可以在其中移动和缩放图像,从而调整图像大小和/或裁剪:

该工具的屏幕截图

我怎么能做到这一点?

Nik*_*ski 15

我有同样的要求.我通过替换cropper lib中的with 解决了PhotoView和Cropper的问题.ImageViewPhotoView

我不得不修改CropWindow类以避免触摸事件无法正确处理:

   public void setImageView(PhotoView pv){
        mPhotoView = pv;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        // If this View is not enabled, don't allow for touch interactions.
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                  boolean dispatch = onActionDown(event.getX(), event.getY());
                  if(!dispatch)
                    mPhotoView.dispatchTouchEvent(event);

                return dispatch;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                getParent().requestDisallowInterceptTouchEvent(false);
                onActionUp();
                return true;

            case MotionEvent.ACTION_MOVE:
                onActionMove(event.getX(), event.getY());
                getParent().requestDisallowInterceptTouchEvent(true);
                return true;

            default:
                return false;
        }
    }
Run Code Online (Sandbox Code Playgroud)

在CropImageView课堂上也改变了一些东西:

private void init(Context context) {

    final LayoutInflater inflater = LayoutInflater.from(context);
    final View v = inflater.inflate(R.layout.crop_image_view, this, true);

    mImageView = (PhotoView) v.findViewById(R.id.ImageView_image2);

    setImageResource(mImageResource);
    mCropOverlayView = (CropOverlayView) v.findViewById(R.id.CropOverlayView);
    mCropOverlayView.setInitialAttributeValues(mGuidelines, mFixAspectRatio, mAspectRatioX, mAspectRatioY);
    mCropOverlayView.setImageView(mImageView);
}
Run Code Online (Sandbox Code Playgroud)

您可以注意到我已在Cropper库中替换ImageView为PhotoViewinside R.layout.crop_image_view.

Cropper库支持固定大小,PhotoView允许您移动和缩放照片,为您提供两全其美的体验.:)

希望能帮助到你.

编辑,对于那些询问如何获取仅在裁剪区域内的图像的人:

private Bitmap getCurrentDisplayedImage(){
        Bitmap result = Bitmap.createBitmap(mImageView.getWidth(), mImageView.getHeight(), Bitmap.Config.RGB_565);
        Canvas c = new Canvas(result);
        mImageView.draw(c);
        return result;
    }
    public Bitmap getCroppedImage() {

        Bitmap mCurrentDisplayedBitmap = getCurrentDisplayedImage();
        final Rect displayedImageRect = ImageViewUtil2.getBitmapRectCenterInside(mCurrentDisplayedBitmap, mImageView);

        // Get the scale factor between the actual Bitmap dimensions and the
        // displayed dimensions for width.
        final float actualImageWidth =mCurrentDisplayedBitmap.getWidth();
        final float displayedImageWidth = displayedImageRect.width();
        final float scaleFactorWidth = actualImageWidth / displayedImageWidth;

        // Get the scale factor between the actual Bitmap dimensions and the
        // displayed dimensions for height.
        final float actualImageHeight = mCurrentDisplayedBitmap.getHeight();
        final float displayedImageHeight = displayedImageRect.height();
        final float scaleFactorHeight = actualImageHeight / displayedImageHeight;

        // Get crop window position relative to the displayed image.
        final float cropWindowX = Edge.LEFT.getCoordinate() - displayedImageRect.left;
        final float cropWindowY = Edge.TOP.getCoordinate() - displayedImageRect.top;
        final float cropWindowWidth = Edge.getWidth();
        final float cropWindowHeight = Edge.getHeight();

        // Scale the crop window position to the actual size of the Bitmap.
        final float actualCropX = cropWindowX * scaleFactorWidth;
        final float actualCropY = cropWindowY * scaleFactorHeight;
        final float actualCropWidth = cropWindowWidth * scaleFactorWidth;
        final float actualCropHeight = cropWindowHeight * scaleFactorHeight;

        // Crop the subset from the original Bitmap.
        final Bitmap croppedBitmap = Bitmap.createBitmap(mCurrentDisplayedBitmap,
                                                         (int) actualCropX,
                                                         (int) actualCropY,
                                                         (int) actualCropWidth,
                                                         (int) actualCropHeight);

        return croppedBitmap;
    }

    public RectF getActualCropRect() {

        final Rect displayedImageRect = ImageViewUtil.getBitmapRectCenterInside(mBitmap, mImageView);

        final float actualImageWidth = mBitmap.getWidth();
        final float displayedImageWidth = displayedImageRect.width();
        final float scaleFactorWidth = actualImageWidth / displayedImageWidth;

        // Get the scale factor between the actual Bitmap dimensions and the displayed
        // dimensions for height.
        final float actualImageHeight = mBitmap.getHeight();
        final float displayedImageHeight = displayedImageRect.height();
        final float scaleFactorHeight = actualImageHeight / displayedImageHeight;

        // Get crop window position relative to the displayed image.
        final float displayedCropLeft = Edge.LEFT.getCoordinate() - displayedImageRect.left;
        final float displayedCropTop = Edge.TOP.getCoordinate() - displayedImageRect.top;
        final float displayedCropWidth = Edge.getWidth();
        final float displayedCropHeight = Edge.getHeight();

        // Scale the crop window position to the actual size of the Bitmap.
        float actualCropLeft = displayedCropLeft * scaleFactorWidth;
        float actualCropTop = displayedCropTop * scaleFactorHeight;
        float actualCropRight = actualCropLeft + displayedCropWidth * scaleFactorWidth;
        float actualCropBottom = actualCropTop + displayedCropHeight * scaleFactorHeight;

        // Correct for floating point errors. Crop rect boundaries should not exceed the
        // source Bitmap bounds.
        actualCropLeft = Math.max(0f, actualCropLeft);
        actualCropTop = Math.max(0f, actualCropTop);
        actualCropRight = Math.min(mBitmap.getWidth(), actualCropRight);
        actualCropBottom = Math.min(mBitmap.getHeight(), actualCropBottom);

        final RectF actualCropRect = new RectF(actualCropLeft,
                                               actualCropTop,
                                               actualCropRight,
                                               actualCropBottom);

        return actualCropRect;
    }




private boolean onActionDown(float x, float y) {    
        final float left = Edge.LEFT.getCoordinate();
        final float top = Edge.TOP.getCoordinate();
        final float right = Edge.RIGHT.getCoordinate();
        final float bottom = Edge.BOTTOM.getCoordinate();    
        mPressedHandle = HandleUtil.getPressedHandle(x, y, left, top, right, bottom, mHandleRadius);    
        if (mPressedHandle == null)
            return false;
        mTouchOffset = HandleUtil2.getOffset(mPressedHandle, x, y, left, top, right, bottom);

        invalidate();
        return true;
    }
Run Code Online (Sandbox Code Playgroud)