How to make selection box with free scaling in android

巧了我就是萌 提交于 2021-02-11 12:24:06

问题


Actually this question or this puzzle needs the heroes in mathematics :)

I have some image and i want to add some selection box to make a crop .. for that i want to control from point 2 to scale horizontally or vertically ..

I find some nice code but it is make scaling eventually in x and y with each together so i am making some manipulation to be able scale any axis dependently ..

I have get success to do that in Y axis but no success for X axis

This is the code :

case MotionEvent.ACTION_MOVE: {
                x2 = event.getX();
                y2 = event.getY();
                dx = x2-x1;
                dy = y2-y1;

                // Use dx and dy to determine the direction of the move
                if(Math.abs(dx) > Math.abs(dy)) {
                    if(dx>0)
                        direction = "right";
                    else
                        direction = "left";
                } else {
                    if(dy>0)
                        direction = "down";
                    else
                        direction = "up";
                }



                if (corner == 1) {
                    if (direction.equals("left") || direction.equals("right") ) {

                        sideX = Math.min(Math.min((Math.max(minimumSideLength, (int) (sideX + Math.floor(event.getX()) - start.x - offset.x))), sideX + (getWidth() - points[1].x - 2 * halfCorner)), sideX + (getHeight() - points[2].y - 2 * halfCorner));
                        points[1].x = points[0].x + sideX;
                        points[3].x = points[0].x + sideX;
                        start.x = points[1].x;
                    }
                    invalidate();
                } else if (corner == 2) {
                    if (direction.equals("up") || direction.equals("down") ) {
                        sideY = Math.min((Math.min((Math.max(minimumSideLength, (int) (sideY + Math.floor(event.getY()) - start.y - offset.y))), sideY + (getHeight() - points[2].y - 2 * halfCorner))), sideY + (getWidth() - points[1].x - 2 * halfCorner));
                        points[2].y = points[0].y + sideY;
                        points[3].y = points[0].y + sideY;
                        start.y = points[2].y;
                    } else if (direction.equals("left") || direction.equals("right") )  {
                    }

                    invalidate();

                }

Important notes:

1- As in the following screenshot, i want to use corner 2 to scale vertically and horizontally and i get it only horizontally succcessfully.

2- As in the following screenshot, i can do vertically successfully with corner 1 so what i need it is using the code of the corner 1 in corner 2 but instead scaling to top i want it to be scaled to bottom when i drag from corner 2 .. i think it is need to replace points with each other and change some math marks like - & +

3- Last note .. you should to know this app in landscape view yes but the activity is in portrait and we rotated views to be like in landscape .. the app needs demands that! That means when you drag horizontally you control the Y axix and when you drag vertically you control X axis.

That's it :)

This is the whole code of the custom view if may it help :

public class IconCropView extends View {

    //contants strings
    private static final String TAG = "IconCropView";

    //drawing objects
    private Paint paint;

    //point objects
    private Point[] points;
    private Point start;
    private Point offset;

    //variable ints
    private int minimumSideLength;
    private int sideX, sideY;
    private int halfCorner;
    private int cornerColor;
    private int edgeColor;
    private int outsideColor;
    private int corner = 5;

    //variable booleans
    private boolean initialized = false;

    //drawables
    private Drawable moveDrawable;
    private Drawable resizeDrawable1, resizeDrawable2, resizeDrawable3;

    int vWidth, vHeight;
    float x1, x2, y1, y2, dx, dy;
    String direction;

    //context
    Context context;

    public IconCropView(Context context) {
        super(context);
        this.context = context;
        init(null);
    }

    public IconCropView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init(attrs);
    }

    public IconCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
    }

    public IconCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.context = context;
        init(attrs);
    }

    private void init(@Nullable AttributeSet attrs) {

        paint = new Paint();
        start = new Point();
        offset = new Point();

        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.IconCropView, 0, 0);

        //initial dimensions
        minimumSideLength = ta.getDimensionPixelSize(R.styleable.IconCropView_minimumSide, 20);
        sideX = minimumSideLength;
        sideY = minimumSideLength;
        halfCorner = (ta.getDimensionPixelSize(R.styleable.IconCropView_cornerSize, 20)) / 2;

        //colors
        cornerColor = ta.getColor(R.styleable.IconCropView_cornerColor, Color.BLACK);
        edgeColor = ta.getColor(R.styleable.IconCropView_edgeColor, Color.WHITE);
        outsideColor = ta.getColor(R.styleable.IconCropView_outsideCropColor, Color.parseColor("#00000088"));


        initCorners(300, 300);

        //init drawables
        moveDrawable = ta.getDrawable(R.styleable.IconCropView_moveCornerDrawable);
        resizeDrawable1 = ta.getDrawable(R.styleable.IconCropView_resizeCornerDrawable);
        resizeDrawable2 = ta.getDrawable(R.styleable.IconCropView_resizeCornerDrawable);
        resizeDrawable3 = ta.getDrawable(R.styleable.IconCropView_resizeCornerDrawable);

        //set drawable colors
        moveDrawable.setTint(cornerColor);
        resizeDrawable1.setTint(cornerColor);
        resizeDrawable2.setTint(cornerColor);
        resizeDrawable3.setTint(cornerColor);

        //recycle attributes
        ta.recycle();

        //set initialized to true
        initialized = true;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //set paint to draw edge, stroke
        if (initialized) {
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setColor(edgeColor);
            paint.setStrokeWidth(4);

            //crop rectangle
            canvas.drawRect(points[0].x + halfCorner, points[0].y + halfCorner, points[0].x + halfCorner + sideX, points[0].y + halfCorner + sideY, paint);

            //set paint to draw outside color, fill
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(outsideColor);

            //top rectangle
            canvas.drawRect(0, 0, canvas.getWidth(), points[0].y + halfCorner, paint);
            //left rectangle
            canvas.drawRect(0, points[0].y + halfCorner, points[0].x + halfCorner, canvas.getHeight(), paint);
            //right rectangle
            canvas.drawRect(points[0].x + halfCorner + sideX, points[0].y + halfCorner, canvas.getWidth(), points[0].y + halfCorner + sideY, paint);
            //bottom rectangle
            canvas.drawRect(points[0].x + halfCorner, points[0].y + halfCorner + sideY, canvas.getWidth(), canvas.getHeight(), paint);

            //set bounds of drawables
            moveDrawable.setBounds(points[0].x, points[0].y, points[0].x + halfCorner * 2, points[0].y + halfCorner * 2);
            resizeDrawable1.setBounds(points[1].x, points[1].y, points[1].x + halfCorner * 2, points[1].y + halfCorner * 2);
            resizeDrawable2.setBounds(points[2].x, points[2].y, points[2].x + halfCorner * 2, points[2].y + halfCorner * 2);
            resizeDrawable3.setBounds(points[3].x, points[3].y, points[3].x + halfCorner * 2, points[3].y + halfCorner * 2);

            //place corner drawables
            moveDrawable.draw(canvas);
            resizeDrawable1.draw(canvas);
            resizeDrawable2.draw(canvas);
            resizeDrawable3.draw(canvas);

//            canvas.rotate(90);

        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //return super.onTouchEvent(event);
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN: {
                x1 = event.getX();
                y1 = event.getY();
                //get the coordinates
                start.x = (int) event.getX();
                start.y = (int) event.getY();

                //get the corner touched if any
                corner = getCorner(start.x, start.y);

                //get the offset of touch(x,y) from corner top-left point
                offset = getOffset(start.x, start.y, corner);

                //account for touch offset in starting point
                start.x = start.x - offset.x;
                start.y = start.y - offset.y;

                break;
            }
            case MotionEvent.ACTION_UP: {

            }
            case MotionEvent.ACTION_MOVE: {
                x2 = event.getX();
                y2 = event.getY();
                dx = x2-x1;
                dy = y2-y1;

                // Use dx and dy to determine the direction of the move
                if(Math.abs(dx) > Math.abs(dy)) {
                    if(dx>0)
                        direction = "right";
                    else
                        direction = "left";
                } else {
                    if(dy>0)
                        direction = "down";
                    else
                        direction = "up";
                }



                if (corner == 1) {
                    if (direction.equals("left") || direction.equals("right") ) {

                        sideX = Math.min(Math.min((Math.max(minimumSideLength, (int) (sideX + Math.floor(event.getX()) - start.x - offset.x))), sideX + (getWidth() - points[1].x - 2 * halfCorner)), sideX + (getHeight() - points[2].y - 2 * halfCorner));
                        points[1].x = points[0].x + sideX;
                        points[3].x = points[0].x + sideX;
                        start.x = points[1].x;
                    }
                    invalidate();
                } else if (corner == 2) {
                    if (direction.equals("up") || direction.equals("down") ) {
                        sideY = Math.min((Math.min((Math.max(minimumSideLength, (int) (sideY + Math.floor(event.getY()) - start.y - offset.y))), sideY + (getHeight() - points[2].y - 2 * halfCorner))), sideY + (getWidth() - points[1].x - 2 * halfCorner));
                        points[2].y = points[0].y + sideY;
                        points[3].y = points[0].y + sideY;
                        start.y = points[2].y;
                    } else if (direction.equals("left") || direction.equals("right") )  {
                    }

                    invalidate();

                } else {
                    points[0].x = Math.max(points[0].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[0].x - 2 * halfCorner - sideX)), 0);
                    points[1].x = Math.max(points[1].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[1].x - 2 * halfCorner)), sideX);
                    points[2].x = Math.max(points[2].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[2].x - 2 * halfCorner - sideX)), 0);
                    points[3].x = Math.max(points[3].x + (int) Math.min(Math.floor((event.getX() - start.x - offset.x)), Math.floor(getWidth() - points[3].x - 2 * halfCorner)), sideX);

                    points[0].y = Math.max(points[0].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[0].y - 2 * halfCorner - sideY)), 0);
                    points[1].y = Math.max(points[1].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[1].y - 2 * halfCorner - sideY)), 0);
                    points[2].y = Math.max(points[2].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[2].y - 2 * halfCorner)), sideY);
                    points[3].y = Math.max(points[3].y + (int) Math.min(Math.floor((event.getY() - start.y - offset.y)), Math.floor(getHeight() - points[3].y - 2 * halfCorner)), sideY);

                    start.x = points[0].x;
                    start.y = points[0].y;
                    invalidate();
                }
                break;
            }
        }
        return true;
    }

    private int getCorner(float x, float y) {
        int corner = 5;
        for (int i = 0; i < points.length; i++) {
            float dx = x - points[i].x;
            float dy = y - points[i].y;
            int max = halfCorner * 2;
            if (dx <= max && dx >= 0 && dy <= max && dy >= 0) {
                return i;
            }
        }
        return corner;
    }

    private void initCorners(int width, int height) {
        //initialize corners;
        points = new Point[4];

        points[0] = new Point();
        points[1] = new Point();
        points[2] = new Point();
        points[3] = new Point();

        //init corner locations;
        //top left
        points[0].x = 0 + width;
        points[0].y = 0 + height;

        //top right
        points[1].x = minimumSideLength + width;
        points[1].y = 0 + height;

        //bottom left
        points[2].x = 0 + width;
        points[2].y = minimumSideLength + height;

        //bottom right
        points[3].x = minimumSideLength + width;
        points[3].y = minimumSideLength + height;
    }

    private Point getOffset(int left, int top, int corner) {
        Point offset = new Point();
        if (corner == 5) {
            offset.x = 0;
            offset.y = 0;
        } else {
            offset.x = left - points[corner].x;
            offset.y = top - points[corner].y;
        }
        return offset;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

来源:https://stackoverflow.com/questions/62976624/how-to-make-selection-box-with-free-scaling-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!