Cutom ImageView Обрезка как WhatsApp - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь создать пользовательскую обрезку изображений, например, WhatsApp, где пользователь загружает изображение профиля, а затем пользователь получает обрезчик прямоугольной формы, который позволяет пользователю обрезать изображение по своему усмотрению. Я не хочу использовать какую-либо библиотеку

Согласно этому ответу я успешно получаю перетаскиваемое изображение поверх изображения, и оно работает нормально, но в этом коде есть проблема, которую я не могу исправить. Я комментирую его github , но он больше не поддерживает этот код.

Что я пробовал до сих пор:

Начальные точки на конструкторе

public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        setFocusable(true); // necessary for getting the touch events
        canvas = new Canvas();
points[0] = new Point();
points[0].x = 150;
points[0].y = 20;
points[1] = new Point();
points[1].x = 150;
points[1].y = 20;
points[2] = new Point();
points[2].x = 150;
points[2].y = 20;
points[3] = new Point();
points[3].x = 150;
points[3].y = 20;
    }

Установить вручную значение onDraw для левой, правой, верхней, нижней переменных

// the method that draws the balls

    @Override
    protected void onDraw(Canvas canvas) {
        if(points[3]==null) //point4 null when user did not touch and move on screen.
            return;
        int left, top, right, bottom;
        left = 150;
        top = 50;
        right = 150;
        bottom = 50;
        for (int i = 1; i < points.length; i++) {
            left = left > points[i].x ? points[i].x:left;
            top = top > points[i].y ? points[i].y:top;
            right = right < points[i].x ? points[i].x:right;
            bottom = bottom < points[i].y ? points[i].y:bottom;
        }
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(5);

        //draw stroke
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.parseColor("#AADB1255"));
        paint.setStrokeWidth(2);
        canvas.drawRect(
                    left + colorballs.get(0).getWidthOfBall() / 2,
                    top + colorballs.get(0).getWidthOfBall() / 2, 
                    right + colorballs.get(2).getWidthOfBall() / 2, 
                    bottom + colorballs.get(2).getWidthOfBall() / 2, paint);
        //fill the rectangle
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.parseColor("#55DB1255"));
        paint.setStrokeWidth(0);
        canvas.drawRect(
                left + colorballs.get(0).getWidthOfBall() / 2,
                top + colorballs.get(0).getWidthOfBall() / 2, 
                right + colorballs.get(2).getWidthOfBall() / 2, 
                bottom + colorballs.get(2).getWidthOfBall() / 2, paint);

        //draw the corners
        BitmapDrawable bitmap = new BitmapDrawable();
        // draw the balls on the canvas
        paint.setColor(Color.BLUE);
        paint.setTextSize(18);
        paint.setStrokeWidth(0);
        for (int i =0; i < colorballs.size(); i ++) {
            ColorBall ball = colorballs.get(i);
            canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
                    paint);

            canvas.drawText("" + (i+1), ball.getX(), ball.getY(), paint);
        }
    }

Так что мне нужно исправить несколько проблем в этом. Пожалуйста, помогите

  1. Все 4 точки перекрывают друг друга при первом запуске и только после того, как становятся видимыми после касания пользователем экрана. Я пытался растянуть 4 точки на 50% от фона ImageView, но не смог.

  2. После успешного выбора определенной области для обрезки. Как получить фоновое изображение этого региона (пожалуйста, просто дайте мне представление, как это сделать).

1 Ответ

2 голосов
/ 13 мая 2019

1. All 4 dots overlapping each other at first launch and only after visible after user touch the screen. I tried to make 4 dots stretch at 50% of background ImageView but failed to do so.

Ответ: вы должны установить правильное начальное значение для массива точек, исходный ответ Кодовая логика - это назначить массив точек, когда сенсорный экран пальца int onTouchEvent() MotionEvent.ACTION_DOWN введите и лишите законной силы представление, тогда представление выполнит onDraw(), чтобы нарисовать прямоугольник.

Так что, если вы хотите показать прямоугольник обрезки, прежде чем касаться экрана, вы должны установить правильное значение для массива точек (может быть,центр зрения с фиксированными квадратами ширины и высоты, вы должны рассчитать) и вручную добавить нарисовать код прямоугольника в методе onDraw().

2. After successfully selecting particular area to crop. How to get background imageview of that region(please just give me idea how to do this).

Ответ: когда вы получили определенную областьчтобы обрезать, вы должны знать информацию о координатах области.

(1) получить исходное растровое изображение, вы показали изображение в фоновом изображении, чтобы вы могли получить исходное растровое изображение или декодировать растровое изображение изфайл или ресурс

(2) выполнить операцию кадрирования

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.xyz);

//you also can use other logic to get a bitmap, this according to your app logic

//create a crop area rectangle
//this crop area rectangle should calculate from the points array
Bitmap croppedBitmap = Bitmap.createBitmap(bmp, x, y, cropWidth, cropHeight);

, затем вы можете получить обрезанное растровое изображение.

Надеюсь, что эти советы могут дать вам представление о том, что архивироватьвы хотите.

Вот демонстрационная ссылка и GIF


package com.image.crop;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


public class DrawView extends View {

    Point[] points = new Point[4];

    /**
     * point1 and point 3 are of same group and same as point 2 and point4
     */
    int groupId = -1;
    private ArrayList<ColorBall> colorballs = new ArrayList<>();

    private int mStrokeColor = Color.parseColor("#AADB1255");
    private int mFillColor = Color.parseColor("#55DB1255");
    private Rect mCropRect = new Rect();

    // array that holds the balls
    private int balID = 0;
    // variable to know what ball is being dragged
    Paint paint;

    public DrawView(Context context) {
        this(context, null);
    }

    public DrawView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public DrawView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        paint = new Paint();
        setFocusable(true); // necessary for getting the touch events
    }

    private void initRectangle(int X, int Y) {
        //initialize rectangle.
        points[0] = new Point();
        points[0].x = X;
        points[0].y = Y;

        points[1] = new Point();
        points[1].x = X;
        points[1].y = Y + 30;

        points[2] = new Point();
        points[2].x = X + 30;
        points[2].y = Y + 30;

        points[3] = new Point();
        points[3].x = X +30;
        points[3].y = Y;

        balID = 2;
        groupId = 1;
        // declare each ball with the ColorBall class
        for (int i = 0; i < points.length; i++) {
            colorballs.add(new ColorBall(getContext(), R.drawable.gray_circle, points[i], i));
        }
    }

    // the method that draws the balls
    @Override
    protected void onDraw(Canvas canvas) {
        if(points[3]==null) {
            //point4 null when view first create
            initRectangle(getWidth() / 2, getHeight() / 2);
        }

        int left, top, right, bottom;
        left = points[0].x;
        top = points[0].y;
        right = points[0].x;
        bottom = points[0].y;
        for (int i = 1; i < points.length; i++) {
            left = left > points[i].x ? points[i].x : left;
            top = top > points[i].y ? points[i].y : top;
            right = right < points[i].x ? points[i].x : right;
            bottom = bottom < points[i].y ? points[i].y : bottom;
        }
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(5);

        //draw stroke
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(mStrokeColor);
        paint.setStrokeWidth(2);

        mCropRect.left = left + colorballs.get(0).getWidthOfBall() / 2;
        mCropRect.top = top + colorballs.get(0).getWidthOfBall() / 2;
        mCropRect.right = right + colorballs.get(2).getWidthOfBall() / 2;
        mCropRect.bottom = bottom + colorballs.get(3).getWidthOfBall() / 2;
        canvas.drawRect(mCropRect, paint);

        //fill the rectangle
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(mFillColor);
        paint.setStrokeWidth(0);
        canvas.drawRect(mCropRect, paint);

        // draw the balls on the canvas
        paint.setColor(Color.RED);
        paint.setTextSize(18);
        paint.setStrokeWidth(0);
        for (int i =0; i < colorballs.size(); i ++) {
            ColorBall ball = colorballs.get(i);
            canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
                    paint);

            canvas.drawText("" + (i+1), ball.getX(), ball.getY(), paint);
        }
    }

    // events when touching the screen
    public boolean onTouchEvent(MotionEvent event) {
        int eventAction = event.getAction();

        int X = (int) event.getX();
        int Y = (int) event.getY();

        switch (eventAction) {

            case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on
                // a ball
                if (points[0] == null) {
                    initRectangle(X, Y);
                } else {
                    //resize rectangle
                    balID = -1;
                    groupId = -1;
                    for (int i = colorballs.size()-1; i>=0; i--) {
                        ColorBall ball = colorballs.get(i);
                        // check if inside the bounds of the ball (circle)
                        // get the center for the ball
                        int centerX = ball.getX() + ball.getWidthOfBall();
                        int centerY = ball.getY() + ball.getHeightOfBall();
                        paint.setColor(Color.CYAN);
                        // calculate the radius from the touch to the center of the
                        // ball
                        double radCircle = Math
                                .sqrt((double) (((centerX - X) * (centerX - X)) + (centerY - Y)
                                        * (centerY - Y)));

                        if (radCircle < ball.getWidthOfBall()) {

                            balID = ball.getID();
                            if (balID == 1 || balID == 3) {
                                groupId = 2;
                            } else {
                                groupId = 1;
                            }
                            invalidate();
                            break;
                        }
                        invalidate();
                    }
                }
                break;

            case MotionEvent.ACTION_MOVE: // touch drag with the ball

                if (balID > -1) {
                    // move the balls the same as the finger
                    colorballs.get(balID).setX(X);
                    colorballs.get(balID).setY(Y);

                    paint.setColor(Color.CYAN);
                    if (groupId == 1) {
                        colorballs.get(1).setX(colorballs.get(0).getX());
                        colorballs.get(1).setY(colorballs.get(2).getY());
                        colorballs.get(3).setX(colorballs.get(2).getX());
                        colorballs.get(3).setY(colorballs.get(0).getY());
                    } else {
                        colorballs.get(0).setX(colorballs.get(1).getX());
                        colorballs.get(0).setY(colorballs.get(3).getY());
                        colorballs.get(2).setX(colorballs.get(3).getX());
                        colorballs.get(2).setY(colorballs.get(1).getY());
                    }

                    invalidate();
                }

                break;

            case MotionEvent.ACTION_UP:
                // touch drop - just do things here after dropping
                // doTheCrop()
                break;
        }
        // redraw the canvas
        invalidate();
        return true;
    }

    public void doTheCrop() {
        Bitmap sourceBitmap = null;
        Drawable backgroundDrawable = getBackground();
        if (backgroundDrawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable;
            if(bitmapDrawable.getBitmap() != null) {
                sourceBitmap = bitmapDrawable.getBitmap();
            }
        }
        if (sourceBitmap != null) {
            //source bitmap was scaled, you should calculate the rate
            float widthRate = ((float) sourceBitmap.getWidth()) / getWidth();
            float heightRate =  ((float) sourceBitmap.getHeight()) / getHeight();

            //crop the source bitmap with rate value
            int left = (int) (mCropRect.left * widthRate);
            int top = (int) (mCropRect.top * heightRate);
            int right = (int) (mCropRect.right * widthRate);
            int bottom = (int) (mCropRect.bottom * heightRate);
            Bitmap croppedBitmap = Bitmap.createBitmap(sourceBitmap, left, top, right - left, bottom - top);
            BitmapDrawable drawable = new BitmapDrawable(getResources(), croppedBitmap);
            setBackground(drawable);
        }
    }

    public static class ColorBall {

        Bitmap bitmap;
        Context mContext;
        Point point;
        int id;

        public ColorBall(Context context, int resourceId, Point point, int id) {
            this.id = id;
            bitmap = BitmapFactory.decodeResource(context.getResources(),
                    resourceId);
            mContext = context;
            this.point = point;
        }

        public int getWidthOfBall() {
            return bitmap.getWidth();
        }

        public int getHeightOfBall() {
            return bitmap.getHeight();
        }

        public Bitmap getBitmap() {
            return bitmap;
        }

        public int getX() {
            return point.x;
        }

        public int getY() {
            return point.y;
        }

        public int getID() {
            return id;
        }

        public void setX(int x) {
            point.x = x;
        }

        public void setY(int y) {
            point.y = y;
        }
    }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...