I want to create a rectangular shape that will be resized with the touches of the user. Below image is a good example of what i want to do:
Is there any example like that? What do I need to study to implement this?
Thanks in advance,
Chintan Rathod's answer was great solution but there are something wrong when He draws the rectangle. I just edit some lines of code to make it works correctly with user touch event. Now, you can add this view to your layout then touch to draw.
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.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.ihnel.englishpronounciation.R;
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<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
// 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 = 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(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);
}
}
// 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) {
//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 (Point pt : points) {
colorballs.add(new ColorBall(getContext(), R.drawable.ic_circle, pt));
}
} 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
break;
}
// redraw the canvas
invalidate();
return true;
}
public static class ColorBall {
Bitmap bitmap;
Context mContext;
Point point;
int id;
static int count = 0;
public ColorBall(Context context, int resourceId, Point point) {
this.id = count++;
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;
}
}
}
To implement a custom view, you derive a class from View :) Override onDraw() for looks, override onTouchEvent() for input processing. Note that in Android, you cannot draw on view outside onDraw(); if you want to refresh the view, call invalidate().
You can implement draggable corners as separate views. For looks, just use ready-made images (feel free to derive from ImageView). Dragging is implemented as moving your view in response to touch events. RelativeLayout is your friend for arbitrary view positining.
You can add homemade views to the layout; just go to XML editing and type a <com.mypackage.MyViewClass> element.
Following code is to draw rectangle on touch base.
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.common.Utils;
import com.example.rectangleoverlay.R;
public class DrawView extends View {
Point point1, point3;
Point point2, point4;
/**
* point1 and point 3 are of same group and same as point 2 and point4
*/
int groupId = -1;
private ArrayList<ColorBall> colorballs = new ArrayList<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
// the method that draws the balls
#Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFCCCCCC); //if you want another background color
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#55000000"));
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
canvas.drawPaint(paint);
paint.setColor(Color.parseColor("#55FFFFFF"));
if (groupId == 1) {
canvas.drawRect(point1.x + colorballs.get(0).getWidthOfBall() / 2,
point3.y + colorballs.get(2).getWidthOfBall() / 2, point3.x
+ colorballs.get(2).getWidthOfBall() / 2, point1.y
+ colorballs.get(0).getWidthOfBall() / 2, paint);
} else {
canvas.drawRect(point2.x + colorballs.get(1).getWidthOfBall() / 2,
point4.y + colorballs.get(3).getWidthOfBall() / 2, point4.x
+ colorballs.get(3).getWidthOfBall() / 2, point2.y
+ colorballs.get(1).getWidthOfBall() / 2, paint);
}
BitmapDrawable mBitmap;
mBitmap = new BitmapDrawable();
// draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
new 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
balID = -1;
groupId = -1;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
Utils.logd("Id : " + ball.getID());
Utils.logd("getX : " + ball.getX() + " getY() : " + ball.getY());
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)));
Utils.logd("X : " + X + " Y : " + Y + " centerX : " + centerX
+ " CenterY : " + centerY + " radCircle : " + radCircle);
if (radCircle < ball.getWidthOfBall()) {
balID = ball.getID();
Utils.logd("Selected ball : " + balID);
if (balID == 1 || balID == 3) {
groupId = 2;
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} else {
groupId = 1;
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
break;
}
invalidate();
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > -1) {
Utils.logd("Moving Ball : " + balID);
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());
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} 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());
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public void shade_region_between_points() {
canvas.drawRect(point1.x, point3.y, point3.x, point1.y, paint);
}
}
Following class is used to store objects
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
public class ColorBall {
Bitmap bitmap;
Context mContext;
Point point;
int id;
static int count = 0;
public ColorBall(Context context, int resourceId, Point point) {
this.id = count++;
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;
}
}
Working Demonstration https://www.youtube.com/watch?v=BfYd7Xa-tCc
I wasn't happy with the highest rated answers for a couple of reasons.
they were not easily usable as a view in xml--the attributes are missing so the view is not easily recyclable.
it seemed silly to be making bitmaps when dropping in a drawable in xml is easier
they don't account for the edges of the view
they don't prevent inversion of the rectangle by dragging too far to the left or top
they don't account for the offset from the touch position to the center of the corner points
they both depend on a depreciated bitmap method
and most importantly, I couldn't get either of them to actually work
I grant that my solution is specialized to a square view, but it can be adjusted fairly easily to have independent X and Y side lengths.
place this in the res/values folder:
custom_attributes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="IconCropView">
<attr name="minimumSide" format="dimension"/>
<attr name="resizeCornerDrawable" format="reference"/>
<attr name="moveCornerDrawable" format="reference"/>
<attr name="cornerColor" format="color"/>
<attr name="edgeColor" format="color" />
<attr name="outsideCropColor" format="color" />
<attr name="cornerSize" format="dimension" />
</declare-styleable>
</resources>
Add this to a java package
IconCropView.java
package your_package;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import your_package.R;
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 side;
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;
//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);
side = 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"));
//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;
points[0].y = 0;
//top right
points[1].x = minimumSideLength;
points[1].y = 0;
//bottom left
points[2].x = 0;
points[2].y = minimumSideLength;
//bottom right
points[3].x = minimumSideLength;
points[3].y = minimumSideLength;
//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 + side, points[0].y + halfCorner + side, 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 + side, points[0].y + halfCorner, canvas.getWidth(), points[0].y + halfCorner + side, paint);
//bottom rectangle
canvas.drawRect(points[0].x + halfCorner, points[0].y + halfCorner + side, 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);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:{
//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:{
if(corner == 0) {
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 - side)), 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)), side);
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 - side)), 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)), side);
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 - side)), 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 - side)), 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)), side);
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)), side);
start.x = points[0].x;
start.y = points[0].y;
invalidate();
}else if (corner == 1){
side = Math.min((Math.min((Math.max(minimumSideLength, (int)(side + Math.floor(event.getX()) - start.x - offset.x))), side + (getWidth() - points[1].x - 2* halfCorner ))),side + (getHeight() - points[2].y - 2* halfCorner ));
points[1].x = points[0].x + side;
points[3].x = points[0].x + side;
points[3].y = points[0].y + side;
points[2].y = points[0].y + side;
start.x = points[1].x;
invalidate();
}else if (corner == 2){
side = Math.min((Math.min((Math.max(minimumSideLength, (int)(side + Math.floor(event.getY()) - start.y - offset.y))), side + (getHeight() - points[2].y - 2* halfCorner ))),side + (getWidth() - points[1].x - 2* halfCorner ));
points[2].y = points[0].y + side;
points[3].y = points[0].y + side;
points[3].x = points[0].x + side;
points[1].x = points[0].x + side;
start.y = points[2].y;
invalidate();
}else if (corner == 3){
side = Math.min((Math.min((Math.min((Math.max(minimumSideLength, (int)(side + Math.floor(event.getX()) - start.x - offset.x))), side + (getWidth() - points[3].x - 2* halfCorner ))),side + (getHeight() - points[3].y - 2* halfCorner ))), Math.min((Math.min((Math.max(minimumSideLength, (int)(side + Math.floor(event.getY()) - start.y - offset.y))), side + (getHeight() - points[3].y - 2* halfCorner ))),side + (getWidth() - points[3].x - 2* halfCorner )));
points[1].x = points[0].x + side;
points[3].x = points[0].x + side;
points[3].y = points[0].y + side;
points[2].y = points[0].y + side;
start.x = points[3].x;
points[2].y = points[0].y + side;
points[3].y = points[0].y + side;
points[3].x = points[0].x + side;
points[1].x = points[0].x + side;
start.y = points[3].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 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);
}
}
In your your layout xml:
You must specify a drawable move corner
You must specify a drawable for the resize corners
corner size defaults to 20px
minimumSide must be at least corner size--default value is 20px
You must include the namespace "http://schemas.android.com/apk/res-auto" in your root view (I used the alias, xlmn:app="http://schemas.android.com/apk/res-auto")
example xml layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="#color/primary"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/crop_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:srcCompat="#mipmap/ic_launcher" />
<your_package.IconCropView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent"
app:minimumSide="60dp"
app:resizeCornerDrawable="#drawable/adjust_edge_circle"
app:moveCornerDrawable="#drawable/move_box_circle"
app:cornerColor="#color/turq"
app:edgeColor="#color/colorPrimary"
app:outsideCropColor="#color/transparent_50"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:cornerSize="20dp"/>
The edited answer of Nguyen Minh Binh worked for me. But I needed to add a lite fix to prevent the ball id to get out of range. This occurred for me if I had to reopen the activity hosting the custom view. I fixed these line:
this.id = count++;
to:
if (count > 3) count = 0;
this.id = count++;
The following code is a C# version (I am currently developing app on MonoDroid/Xamarin) of the requested code, but with some improvements and the ability to drag the rectangle. Still want to add some features, will edit it later.
namespace ImagePlayground
{
[Activity (Label = "MyView2")]
public class MyView2 : View
{
Graphics.Point[] points = new Graphics.Point[4];
// Array that hold the circle
private List<ResizeCircle> circles = new List<ResizeCircle>();
// Variable to keep tracking of which circle is being dragged
private int circleId = -1;
// Points are grouped in groups of two so there's always only one fixed point
// groupId = 0 > Touch Inside the Rectangle
// groupId = 1 > Points 0 and 2
// groupId = 2 > Points 1 and 3
int groupId = -1;
// FirstTouch's Coordinate for Tracking on Dragging
int xFirstTouch = 0;
int yFirstTouch = 0;
/** Main Bitmap **/
private Bitmap mBitmap = null;
/** Measured Size of the View **/
private Rect mMeasuredRect;
/** Paint to Draw Rectangles **/
private Paint mRectPaint;
public MyView2(Context ctx) : base (ctx){
init (ctx);
}
public MyView2 (Context ctx, IAttributeSet attrs) : base (ctx, attrs){
init (ctx);
}
public MyView2 (Context ctx, IAttributeSet attrs, int defStyle) : base(ctx,attrs,defStyle){
init (ctx);
}
private void init(Context ctx){
// For Touch Events
Focusable = true;
// Draw the Image on the Background
mBitmap = BitmapFactory.DecodeResource(ctx.Resources, Resource.Drawable.bg);
// Sets up the paint for the Drawable Rectangles
mRectPaint = new Paint ();
mRectPaint.Color = Android.Graphics.Color.Aqua;
mRectPaint.StrokeWidth = 4;
mRectPaint.SetStyle (Paint.Style.Stroke);
}
protected override void OnDraw(Canvas canvas){
// Background Bitmap to Cover all Area
canvas.DrawBitmap(mBitmap, null, mMeasuredRect, null);
// Just draw the points only if it has already been initiated
if (points [3] != null) {
int left, top, right, bottom;
left = points [0].X;
top = points [0].Y;
right = points [0].X;
bottom = points [0].Y;
// Sets the circles' locations
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;
}
mRectPaint.AntiAlias = true;
mRectPaint.Dither = true;
mRectPaint.StrokeJoin = Paint.Join.Round;
mRectPaint.StrokeWidth = 5;
mRectPaint.SetStyle (Paint.Style.Stroke);
mRectPaint.Color = Graphics.Color.ParseColor ("#0079A3");
canvas.DrawRect (
left + circles [0].GetCircleWidth () / 2,
top + circles [0].GetCircleWidth () / 2,
right + circles [2].GetCircleWidth () / 2,
bottom + circles [2].GetCircleWidth () / 2, mRectPaint);
// Fill The Rectangle
mRectPaint.SetStyle (Paint.Style.Fill);
mRectPaint.Color = Graphics.Color.ParseColor ("#B2D6E3");
mRectPaint.Alpha = 75;
mRectPaint.StrokeWidth = 0;
canvas.DrawRect (
left + circles [0].GetCircleWidth () / 2,
top + circles [0].GetCircleWidth () / 2,
right + circles [2].GetCircleWidth () / 2,
bottom + circles [2].GetCircleWidth () / 2, mRectPaint);
// DEBUG
mRectPaint.Color = Graphics.Color.Red;
mRectPaint.TextSize = 18;
mRectPaint.StrokeWidth = 0;
// Draw every circle on the right position
for (int i = 0; i < circles.Count (); i++) {
ResizeCircle circle = circles [i];
float x = circle.GetX ();
float y = circle.GetY ();
canvas.DrawBitmap (circle.GetBitmap (), x, y,
mRectPaint);
// DEBUG
// canvas.DrawText ("" + (i + 1), circle.GetX (), circle.GetY (), mRectPaint);
}
}
}
public override bool OnTouchEvent(MotionEvent e){
// Get the Coordinates of Touch
int xTouch = (int) e.GetX ();
int yTouch = (int) e.GetY ();
int actionIndex = e.ActionIndex;
switch (e.ActionMasked) {
// In case user touch the screen
case MotionEventActions.Down:
// If no points were created
if (points [0] == null) {
// Offset to create the points
int offset = 60;
// Initialize a new Rectangle.
points [0] = new Graphics.Point ();
points [0].X = xTouch;
points [0].Y = yTouch;
points [1] = new Graphics.Point ();
points [1].X = xTouch;
points [1].Y = yTouch + offset;
points [2] = new Graphics.Point ();
points [2].X = xTouch + offset;
points [2].Y = yTouch + offset;
points [3] = new Graphics.Point ();
points [3].X = xTouch + offset;
points [3].Y = yTouch;
// Add each circle to circles array
foreach (Graphics.Point pt in points) {
circles.Add (new ResizeCircle (Context, Resource.Drawable.circle, pt));
}
} else {
// Register Which Circle (if any) th user has touched
groupId = getTouchedCircle (xTouch, yTouch);
xFirstTouch = xTouch;
yFirstTouch = yTouch;
}
break;
case MotionEventActions.PointerDown:
break;
case MotionEventActions.Move:
if (groupId == 1 || groupId == 2) {
// Move touched Circle as the finger moves
circles[circleId].SetX(xTouch);
circles[circleId].SetY(yTouch);
// Move the two other circles accordingly
if (groupId == 1) {
circles[1].SetX(circles[0].GetX());
circles[1].SetY(circles[2].GetY());
circles[3].SetX(circles[2].GetX());
circles[3].SetY(circles[0].GetY());
} else {
circles[0].SetX(circles[1].GetX());
circles[0].SetY(circles[3].GetY());
circles[2].SetX(circles[3].GetX());
circles[2].SetY(circles[1].GetY());
}
Invalidate();
} else if (groupId == 0){
// Calculate the delta for the dragging
int xDelta = (xTouch-xFirstTouch);
int yDelta = (yTouch-yFirstTouch);
xFirstTouch = xTouch;
yFirstTouch = yTouch;
// Move each circle accordingly
foreach (ResizeCircle circle in circles) {
circle.SetX (circle.GetX () + xDelta);
circle.SetY (circle.GetY () + yDelta);
}
// Redraw the view
Invalidate ();
}
break;
case MotionEventActions.Up:
break;
default:
break;
}
Invalidate ();
return true;
}
private int getTouchedCircle(int xTouch, int yTouch){
int groupId = -1;
for (int i = 0; i < circles.Count; i++) {
ResizeCircle circle = circles [i];
// Check if the touch was inside the bounds of the circle
int centerX = circle.GetX () + circle.GetCircleWidth ();
int centerY = circle.GetY () + circle.GetCircleHeight ();
// Calculate the radius from the touch to the center of the circle
double radCircle = Math.Sqrt ((double)(((centerX - xTouch) * (centerX - xTouch)) + (centerY - yTouch)
* (centerY - yTouch)));
// If the touch was on one of the circles
if (radCircle < circle.GetCircleWidth ()) {
circleId = circle.GetID ();
if (circleId == 1 || circleId == 3) {
groupId = 2;
break;
} else {
groupId = 1;
break;
}
} else {
// User didn't touch any of the circles nor the inside area
groupId = -1;
}
}
// If the touch wasn't on one of the circles, check if it was inside the rectangle
if (groupId == -1) {
List<int> xCoords = new List<int> ();
List<int> yCoords = new List<int> ();
// Gather Coordinates from all circles
foreach (ResizeCircle circle in circles){
xCoords.Add (circle.GetX());
yCoords.Add (circle.GetY());
}
// Store the max and min coordinates
int minX = xCoords.Min ();
int maxX = xCoords.Max ();
int minY = yCoords.Min ();
int maxY = yCoords.Max ();
// Check if user has touched inside the rectangle
if ((xTouch > minX && xTouch < maxX) && (yTouch > minY && yTouch < maxY)) {
// User has touched inside the Rectangle
groupId = 0;
}
}
return groupId;
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec){
base.OnMeasure (widthMeasureSpec, heightMeasureSpec);
mMeasuredRect = new Rect (0, 0, MeasuredWidth, MeasuredHeight);
}
public class ResizeCircle {
Bitmap bitmap;
Graphics.Point point;
int id;
static int count = 0;
public ResizeCircle(Context context, int resourceId, Graphics.Point point) {
this.id = count++;
bitmap = BitmapFactory.DecodeResource(context.Resources,
resourceId);
Log.Debug("BITMAP" , bitmap.Height.ToString());
this.point = point;
}
public int GetCircleWidth() {
return bitmap.Width;
}
public int GetCircleHeight() {
return bitmap.Height;
}
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;
}
}
}
}
Related
My goal is to draw 3 equals custom views in an Activity. The custom view overrides onTouchEvent. If I add just one custom view in the Activity, by XML or programmatically, all works fine. If I add 2 custom views (the same custom view) the touch event works only for one custom view, the other one is fixed in layout and doesn't intercept anything at all. I've seen other discussions but I can't find the problem.
My custom view class:
public class IconCropView extends View {
//contants strings
private static final String TAG = "IconCropView";
private static final int TEXT_COLOR = Color.RED;
private static final float TEXT_SIZE = 30.0f;
private static final float STROKE_WIDTH = 4.0f;
//drawing objects
private Paint paint;
//text
private Paint textPaint;
//point objects
private Point[] points;
private Point start;
private Point offset;
//variable ints
private int altezzaMinima;
private int altezza;
private int halfCorner;
private int cornerColor;
private int edgeColor;
private int outsideColor;
private int corner = 30;
//variable booleans
private boolean initialized = false;
//drawables
private Drawable moveDrawable;
private Drawable resizeDrawable2;
//context
Context context;
//Rect del canvas
Rect cropBorder;
boolean clickInCropRect;
public IconCropView(Context context) {
super(context);
this.context = context;
init(null,null);
}
public IconCropView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
init(attrs,null);
}
public IconCropView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init(attrs,null);
}
public IconCropView(Context context, Point[] punti) {
super(context);
this.context = context;
init(null,punti);
}
private void init(#Nullable AttributeSet attrs,Point[] punti ){
paint = new Paint();
start = new Point();
offset = new Point();
//initial dimensions
altezzaMinima = 400;
altezza = altezzaMinima;
halfCorner = 25;
//colors
cornerColor = Color.BLACK;
edgeColor = Color.WHITE;
outsideColor =Color.parseColor("#00000088");
//initialize corners;
points = new Point[4];
points[0] = new Point();
points[1] = new Point();
points[2] = new Point();
points[3] = new Point();
if(punti == null) {
//init corner locations;
//top left
points[0].x = 0;
points[0].y = 0;
//top right
points[1].x = 600;
points[1].y = 0;
//bottom left
points[2].x = 0;
points[2].y = altezzaMinima;
//bottom right
points[3].x = 600;
points[3].y = altezzaMinima;
}
if(punti != null){
//init corner locations;
//top left
points[0].x = punti[0].x;
points[0].y = punti[0].y;
//top right
points[1].x = punti[1].x;
points[1].y = punti[1].y;
//bottom left
points[2].x = punti[2].x;
points[2].y = punti[2].y;
//bottom right
points[3].x = punti[3].x;
points[3].y = punti[3].y;
}
//init drawables
resizeDrawable2 = getResources().getDrawable(R.drawable.circle);
//set initialized to true
initialized = true;
//inizializzo testo
textPaint = new Paint();
textPaint.setColor(TEXT_COLOR);
textPaint.setTextSize(TEXT_SIZE);
}
#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);
cropBorder = new Rect(points[0].x + halfCorner, points[0].y + halfCorner,points[0].x + halfCorner + 500,points[0].y + halfCorner + altezza);
//crop rectangle
canvas.drawRect(cropBorder, paint);
//set paint to draw outside color, fill
paint.setStyle(Paint.Style.FILL);
paint.setColor(outsideColor);
resizeDrawable2.setBounds(points[2].x, points[2].y, points[2].x + halfCorner*2, points[2].y + halfCorner*2);
//place corner drawable
resizeDrawable2.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:{
//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;
// dentro il rettangolo
clickInCropRect = cropBorder.contains( start.x, start.y);
break;
}
case MotionEvent.ACTION_MOVE:{
if(corner == 0 || clickInCropRect ) {
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 - (cropBorder.width()))), 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)), altezza);
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 - (cropBorder.width()))), 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)), altezza);
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 - (cropBorder.height()) )), 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 - (cropBorder.height()))), 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)), altezza);
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)), altezza);
start.x = points[0].x+(cropBorder.width()/2);
start.y = points[0].y+(cropBorder.height()/2);
Log.v("TOUCHED", points[0].x + " ");
invalidate();
}
else if (corner == 2){
altezza = Math.min((Math.min((Math.max(altezzaMinima, (int)(altezza + Math.floor(event.getY()) - start.y - offset.y))), altezza + (getHeight() - points[2].y - 2* halfCorner ))), altezza + (getWidth() - points[1].x - 2* halfCorner ));
points[2].y = points[0].y + altezza;
points[3].y = points[0].y + altezza;
points[3].x = points[0].x + altezza;
points[1].x = points[0].x + altezza;
start.y = points[2].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 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);
}
}
In onCreate Activity :
IconCropView iconCrop1 = new IconCropView(context);
IconCropView iconCrop2 = new IconCropView(context,punti);
RelativeLayout myLayout = findViewById(R.id.myLayout);
myLayout .addView(iconCrop1);
myLayout .addView(iconCrop2);
I've put them also in the XML file but the result is the same.
I'll appreciate your helps.
Thank you all.
I solved the problem. The issue wasn't the onTouchEvent but the container where IconCropView was defined in. Before I simply defined an element and added it to the layout. Now in my opinion the correct way is:
Define layout where IconCropView is created in. It should be greater than IconCropview otherwise it can't move with touch:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mImageViewWidth, mImageViewHeight / 4 );
Define IconCropView margins related to its container.
params.setMargins(marginLeft, marginTop, marginRight, marginBottom);
3)Create new IconCropView and add It in the parent layout activity. Mlayout is the main layout of activity:
IconCropView cropView = new IconCropView(context, width, height);
cropView .setLayoutParams(params);
mLayout.addView(cropView);
I hope this can be useful for someone.
I want to draw a resizable box. It should be a square as I move my finger.
I am using the following code for my android app, for re-sizable box drawing with onTouch Event.
http://chintanrathod.com/resizable-rectangle-overlay-on-touch-in-android/
This code exactly meets my requirement with only one exception. It is not limited square. I want to limit it to square as I move my finger. I have tried to limit the calculations by calculating the delta but haven't got succeed.
public class DrawBoxView extends View {
Point[] points = new Point[4];
private OnBoxTouchListener onBoxTouchListener;
Point startMovePoint;
/**
* point1 and point 3 are of same group and same as point 2 and point4
*/
int groupId = -1;
private ArrayList<ColorBall2> colorballs = new ArrayList<ColorBall2>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawBoxView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
public DrawBoxView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawBoxView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
// the method that draws the balls
#Override
protected void onDraw(Canvas canvas) {
if (points[0] == null) {
//initialize rectangle.
points[0] = new Point();
points[0].x = 50;
points[0].y = 20;
points[1] = new Point();
points[1].x = 200;
points[1].y = 20;
points[2] = new Point();
points[2].x = 200;
points[2].y = 170;
points[3] = new Point();
points[3].x = 50;
points[3].y = 170;
balID = 2;
groupId = 1;
// declare each ball with the ColorBall class
int count = 0;
for (Point pt : points) {
colorballs.add(new ColorBall2(getContext(), R.drawable.gray_circle, pt,count++));
}
}
if(points[3]==null) //point4 null when user did not touch and move on screen.
return;
/**My modification to calculate delta**/
int diffWidth = Math.abs(colorballs.get(1).getX() - colorballs.get(0).getX());
int diffHeight = Math.abs(colorballs.get(1).getY() - colorballs.get(0).getY());
/**End of My modification**/
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;
int x_delta = Math.abs(points[0].x - points[1].x);
right = right < points[i].x ? points[i].x : right;
bottom = bottom < points[i].y ? points[i].y : bottom;
/**My modification to calculate delta**/
int y_delta = Math.abs(points[1].y - points[2].y);
if(x_delta != y_delta)
{
int bottom_delta = Math.abs(points[1].y - bottom);
if(bottom_delta < y_delta)
{
bottom = bottom + bottom_delta;
}
else if(bottom_delta > y_delta)
{
}
}
}
/**end of my code**/
Log.e("Left", String.valueOf(left));
Log.e("top", String.valueOf(top));
Log.e("right", String.valueOf(right));
Log.e("bottom", String.valueOf(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.BLACK);
paint.setStrokeWidth(8);
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(getResources().getColor(R.color.app_color_red_transparent));
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 ++) {
ColorBall2 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) {
//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
int count = 0;
for (Point pt : points) {
colorballs.add(new ColorBall2(getContext(), R.drawable.gray_circle, pt,count++));
}
} else {
//resize rectangle
balID = -1;
startMovePoint = new Point(X,Y);
groupId = -1;
for (int i = colorballs.size()-1; i>=0; i--) {
ColorBall2 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());
}
*/
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();
}else{
if (startMovePoint!=null) {
paint.setColor(Color.CYAN);
int diffX = X - startMovePoint.x;
int diffY = Y - startMovePoint.y;
startMovePoint.x = X;
startMovePoint.y = Y;
colorballs.get(0).addX(diffX);
colorballs.get(1).addX(diffX);
colorballs.get(2).addX(diffX);
colorballs.get(3).addX(diffX);
colorballs.get(0).addY(diffY);
colorballs.get(1).addY(diffY);
colorballs.get(2).addY(diffY);
colorballs.get(3).addY(diffY);
if(groupId==1)
canvas.drawRect(points[0].x, points[2].y, points[2].x, points[0].y,
paint);
else
canvas.drawRect(points[1].x, points[3].y, points[3].x, points[1].y,
paint);
invalidate();
}
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public OnBoxTouchListener getOnBoxTouchListener() {
return onBoxTouchListener;
}
public void setOnBoxTouchListener(OnBoxTouchListener onBoxTouchListener) {
this.onBoxTouchListener = onBoxTouchListener;
}
public Rect shade_region_between_points() {
if (points[0] == null && points[2] == null) {
return new Rect(0, 0, 0, 0);
}
else if (points[0] == null) {
return new Rect(0, points[2].y, points[2].x, 0);
}
else if (points[2] == null) {
return new Rect(points[0].x, 0, 0, points[0].y);
}
else
{
return new Rect(points[0].x, points[2].y, points[2].x, points[0].y);
}
}
public Point[] getPoints()
{
return points;
}
}
I have tried to change the formulas with TOUCH_MOVE and onDraw events by calculating the delta X, but I haven't got any success. Anyone can guide to modify this code will be highly appreciated.
Thank you.
I am going to relate to the code in the link you described to make it simple:
From what I understand, the balls in organized in these indexes:
0 3
1 2
To keep this simple, I will refer to each ball as their index.
Before setting X and Y of selected Ball, calculate Delta:
if (balID > -1) {
float deltaX = colorballs.get(ballID).getX() - X;
float deltaY = colorballs.get(ballID).getY() - Y;
colorballs.get(balID).setX(X);
colorballs.get(balID).setY(Y);
Now we use delta when we update balls coordinates:
if(balID == 0){ //Top Left ball
colorballs.get(1).setX(colorballs.get(balID).getX());
colorballs.get(2).setX(colorballs.get(2).getX() + deltaY);
colorballs.get(3).setY(colorballs.get(ballID).getY);
colorballs.get(3).setX(colorballs.get(2).getX());
}
If we move ball 0, this happens:
Dragging 0 up
^ ^
|deltaY | moves alongside 0
0 3 --> Expand by deltaY
1 2 --> Expand by deltaY
Dragging 0 right
deltaX
0 --> 3
^
| Reduce Y by delta X
1 --> 2 --> Expand by deltaY
Since moving down will result in negative delta, it will be handled automatically.
This is the basic concept,
You can do the same to rest of the balls as well by simply replacing the indexes in above snippet.
I want to make an shape with 4 points,then draw and provide to pull angles for user,via touch Events.
E.g. i have an ImageView,where ill fill with an image taken from gallery/camera(nevermind), after that must appear that Shape with 4 points(i think that each point will be an image as little circle) and user can change angles via touch to this Point.
This points is like coordinate,where i want to get this values and make some kind of Perpesctive.
In others words:
ImageView filled with image -> Appears drawed shape with 4 points
User put this points as he want
When work is done,take this coordinates to make an perspective.
So how can i achieve this? Thanks!!
Finally, this article helped me a lot. Pretty the same(trivial).
public class DrawView extends View {
Point point1, point3;
Point point2, point4;
/**
* point1 and point 3 are of same group and same as point 2 and point4
*/
int groupId = -1;
private ArrayList<ColorBall> colorballs = new ArrayList<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
// the method that draws the balls
#Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFCCCCCC); //if you want another background color
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#55000000"));
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
canvas.drawPaint(paint);
paint.setColor(Color.parseColor("#55FFFFFF"));
if (groupId == 1) {
canvas.drawRect(point1.x + colorballs.get(0).getWidthOfBall() / 2,
point3.y + colorballs.get(2).getWidthOfBall() / 2, point3.x
+ colorballs.get(2).getWidthOfBall() / 2, point1.y
+ colorballs.get(0).getWidthOfBall() / 2, paint);
} else {
canvas.drawRect(point2.x + colorballs.get(1).getWidthOfBall() / 2,
point4.y + colorballs.get(3).getWidthOfBall() / 2, point4.x
+ colorballs.get(3).getWidthOfBall() / 2, point2.y
+ colorballs.get(1).getWidthOfBall() / 2, paint);
}
BitmapDrawable mBitmap;
mBitmap = new BitmapDrawable();
// draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
new 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
balID = -1;
groupId = -1;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
Utils.logd("Id : " + ball.getID());
Utils.logd("getX : " + ball.getX() + " getY() : " + ball.getY());
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)));
Utils.logd("X : " + X + " Y : " + Y + " centerX : " + centerX
+ " CenterY : " + centerY + " radCircle : " + radCircle);
if (radCircle < ball.getWidthOfBall()) {
balID = ball.getID();
Utils.logd("Selected ball : " + balID);
if (balID == 1 || balID == 3) {
groupId = 2;
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} else {
groupId = 1;
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
break;
}
invalidate();
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > -1) {
Utils.logd("Moving Ball : " + balID);
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());
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} 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());
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public void shade_region_between_points() {
canvas.drawRect(point1.x, point3.y, point3.x, point1.y, paint);
}
}
I want to add image(bitmap) inside this rectangle code so that the image also re sizes accordingly. when dragging the end points please help me out on this.
I just want to know where to add the bitmap image so that it fits in the below mentioned rectangle code.
public class Rectangler 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<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public Rectangler(Context context)
{
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
public Rectangler(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public Rectangler(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
}
// 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 = 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(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);
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.eight);
canvas.drawBitmap(bmp, colorballs.get(10).getX(), colorballs.get(10).getY(), null);
//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);
}
}
// 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) {
//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 (Point pt : points) {
colorballs.add(new ColorBall(getContext(), R.drawable.ic_circle, pt));
}
} 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
break;
}
// redraw the canvas
invalidate();
return true;
}
}
Here is my color ball class
class ColorBall {
Bitmap bitmap;
Context mContext;
Point point;
int id;
static int count = 0;
public ColorBall(Context context, int resourceId, Point point) {
this.id = count++;
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;
}
}
See the following image
I want to change the shape of highlighted view by dragging its corner.. not necessory the view after dragging the corner should be rectangle it can be any arbitary shape
how to achive this??
now i have done the 4 corners movable on touch event but the shape is not changing
package com.assignment.DragDrop;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
public class DrawView extends View {
Point point1,point2,point3,point4;
private ColorBall[] colorballs = new ColorBall[4]; // array that holds the balls
private int balID = 0; // variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint=new Paint();
setFocusable(true); //necessary for getting the touch events
canvas= new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs[0] = new ColorBall(context,R.drawable.bol_blauw, point1);
colorballs[1] = new ColorBall(context,R.drawable.bol_blauw, point2);
colorballs[2] = new ColorBall(context,R.drawable.bol_groen, point3);
colorballs[3] = new ColorBall(context,R.drawable.bol_geel, point4);
}
// the method that draws the balls
#Override protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xFFCCCCCC); //if you want another background color
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
canvas.drawPaint(paint);
paint.setColor(Color.WHITE);
canvas.drawRect(point1.x+25, point2.x, point3.x+25, point4.x, paint);
BitmapDrawable mBitmap;
mBitmap= new BitmapDrawable();
// canvas.drawBitmap(bitmap, left, top, paint)
// shade_region_between_points();
// canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint);
// canvas.drawLine(point1.x, point1.y, point4.x, point4.y, paint);
// canvas.drawLine(point4.x, point4.y, point3.x, point3.y, paint);
// canvas.drawLine(point2.x, point2.y, point3.x, point3.y, paint);
//draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(), paint);
// canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint);
// canvas.drawRect(point1.x, point2.x, point3.x, point4.x, paint);
}
/*Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
drawable.setBounds( point1.x+25, point2.x, point3.x+25, point4.x);
drawable.draw(canvas);*/
}
// 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
balID = 0;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
int centerX = ball.getX() + 25;
int centerY = ball.getY() + 25;
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)));
// canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint);
// if the radius is smaller then 23 (radius of a ball is 22), then it must be on the ball
if (radCircle < 23){
balID = ball.getID();
canvas.drawRect(point1.x, point2.x, point3.x, point4.x, paint);
invalidate();
break;
}
invalidate();
//canvas.drawRect(point1.x, point2.x, point3.x, point4.x, paint);
// check all the bounds of the ball (square)
//if (X > ball.getX() && X < ball.getX()+50 && Y > ball.getY() && Y < ball.getY()+50){
// balID = ball.getID();
// break;
//}
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > 0) {
try {
colorballs[balID-1].setX(X-25);
colorballs[balID-1].setY(Y-25);
// canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
paint.setColor(Color.CYAN);
canvas.drawRect(point1.x, point2.x, point3.x, point4.x, paint);
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public void shade_region_between_points()
{
canvas.drawRect(point1.x, point2.x, point3.x, point4.x, paint);
}
}
I got this code from internet.
this will able to move corners on touch event but the shape is not moving...
Following code is to draw rectangle on touch base.
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.common.Utils;
import com.example.rectangleoverlay.R;
public class DrawView extends View {
Point point1, point3;
Point point2, point4;
/**
* point1 and point 3 are of same group and same as point 2 and point4
*/
int groupId = -1;
private ArrayList<ColorBall> colorballs = new ArrayList<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
// the method that draws the balls
#Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFCCCCCC); //if you want another background color
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#55000000"));
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
canvas.drawPaint(paint);
paint.setColor(Color.parseColor("#55FFFFFF"));
if (groupId == 1) {
canvas.drawRect(point1.x + colorballs.get(0).getWidthOfBall() / 2,
point3.y + colorballs.get(2).getWidthOfBall() / 2, point3.x
+ colorballs.get(2).getWidthOfBall() / 2, point1.y
+ colorballs.get(0).getWidthOfBall() / 2, paint);
} else {
canvas.drawRect(point2.x + colorballs.get(1).getWidthOfBall() / 2,
point4.y + colorballs.get(3).getWidthOfBall() / 2, point4.x
+ colorballs.get(3).getWidthOfBall() / 2, point2.y
+ colorballs.get(1).getWidthOfBall() / 2, paint);
}
BitmapDrawable mBitmap;
mBitmap = new BitmapDrawable();
// draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
new 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
balID = -1;
groupId = -1;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
Utils.logd("Id : " + ball.getID());
Utils.logd("getX : " + ball.getX() + " getY() : " + ball.getY());
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)));
Utils.logd("X : " + X + " Y : " + Y + " centerX : " + centerX
+ " CenterY : " + centerY + " radCircle : " + radCircle);
if (radCircle < ball.getWidthOfBall()) {
balID = ball.getID();
Utils.logd("Selected ball : " + balID);
if (balID == 1 || balID == 3) {
groupId = 2;
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} else {
groupId = 1;
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
break;
}
invalidate();
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > -1) {
Utils.logd("Moving Ball : " + balID);
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());
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} 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());
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public void shade_region_between_points() {
canvas.drawRect(point1.x, point3.y, point3.x, point1.y, paint);
}
}
Following class is used to store objects
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
public class ColorBall {
Bitmap bitmap;
Context mContext;
Point point;
int id;
static int count = 0;
public ColorBall(Context context, int resourceId, Point point) {
this.id = count++;
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;
}
}
Its just like when we crop image then it increase the size of your rectangle.Then we can save our view as new bitmap.So you can take a help from this question.
This explain the almost same thing as you required.
OR
if it is layout then we can set new Layout-Param with new height and width when we touch any view