问题
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