Get touch event on Paint object in android - android

I'm drawing a circle using 7 paint objects as below on a canvas in my android app. same paint object can be used more than one time to draw this circle.
Now I want to display color name of touched paint object, when user touch on each color.
How can I do this ?

Use on Touch Event for the same like :
public class TouchImage extends ImageView {
Paint paint = new Paint();
Point point = new Point();
public TouchImage(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.BLUE);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(point.x, point.y, 10, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
point.x = event.getX();
point.y = event.getY();
invalidate();
}
return true;
}
class Point {
float x, y;
}
}

You should have the positions for all color circles.
Inside onTouchEvent() you can compare the distance between each color circle and touch position with color circles radius.
If distance is less than radius (and maybe greater than min value, so only the colors are touchable and not the empty area inside circle) you could otbtain the angle and determine selected color this way.
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
for (colorCircle c : allCircles) {
float distance = sqrt ((event.getX() - c.getX())^2 +
((event.getY() - c.getY())^2);
if (distance < c.getRadius()) {
for (coloredPart cPart : c) {
if (event.getX() > (Math.cos(cPart.getMinAngle) * c.getRadius)
+ c.getX() &&
event.getX() < (Math.cos(cPart.getMaxAngle) * c.getRadius)
+ c.getX() &&
event.getY() > (Math.sin(cPart.getMinAngle) * c.getRadius)
+ c.getY() &&
event.getY() < (Math.sin(cPart.getMaxAngle) * c.getRadius)
+ c.getY() && ) {
// cPart was touched
}
}
}
}
}
return true;
}

Related

Android: How to draw circle within two point?

this is my current code
Path path_eclipse = new Path();
float radius = (float) (Math.sqrt(Math.pow(r.stopX - r.startX, 2.0f) + Math.pow(r.stopY - r.startY, 2.0f)) / 2.0f);
path_eclipse.addCircle(r.startX, r.startY, radius, Path.Direction.CCW);
canvas.drawPath(path_eclipse, paint);
with this code I am getting as output:
But I want to draw circle like this:
UPDATED Source code: This source code worked in my case
[SOLVED]
[OnDraw]
#Override
protected void onDraw(Canvas canvas) {
Path path_eclipse = new Path();
float centerX = (r.startX + r.stopX) /2;
float centerY = (r.startY + r.stopY) /2;
float radius = (float)Math.sqrt((r.stopX - r.startX)*(r.stopX - r.startX)+(r.stopY - r.startY)*(r.stopY - r.startY));
path_eclipse.addCircle(centerX, centerY, radius/2, Path.Direction.CCW);
canvas.drawPath(path_eclipse,paint);
}
[OnTouchEvent]
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = eventX;
startY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
stopX = eventX;
stopY = eventY;
break;
case MotionEvent.ACTION_UP:
stopX = eventX;
stopY = eventY;
break;
default:
return false;
}
invalidate();
return true;
}
The first two paramateres of addCircle are the x and y coordinates of the center. Assuming A and B are the furthest distance from each other on the circle you want, then the center should a point equidistant to both, hence:
float centerX = (pointA.x + pointB.x) /2
float centerY = (pointA.y + pointB.y) /2
And your radius should be, the distance between A and B, thus:
float radius = (Math.sqrt(Math.pow(x2−x1, 2) + Math.pow(y2−y1, 2))) / 2
Mid points
int mx=(r.stopX + r.startX)/2;
int my= (r.stopy+r.startY)/2;
Radius
float radius = Math.sqrt(Math.pow(r.stopX - my, 2)
+ Math.pow(r.stopY - my, 2));
Edited
I have used code below
public class CustomView extends View {
private Paint paint;
private Circle circle;
private List<Point> points;
public final int CIRCLE_BETWEEN_TWO_POINTS = 1;
private int viewType;
{
paint = new Paint();
points = new ArrayList<>();
}
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
switch (viewType) {
case CIRCLE_BETWEEN_TWO_POINTS:
drawView(canvas);
break;
}
}
private void drawView(Canvas canvas){
for(Point point:points){
drawCircle(canvas,new Circle(point.x,point.y,10),false);
}
drawCircle(canvas,circle,true);
}
private void drawCircle(Canvas canvas,Circle circle, boolean isStroke){
paint.reset();
paint.setAntiAlias(true);
if(isStroke){
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
}else {
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
}
canvas.drawCircle(circle.getX(), circle.getY(), circle.getRadius(), paint);
}
public void drawCircleBetweenTwoPoints(int x1, int y1, int x2, int y2) {
viewType = CIRCLE_BETWEEN_TWO_POINTS;
points.clear();
points.add(new Point(x1, y1));
points.add(new Point(x2, y2));
int mx = (x1 + x2) / 2;
int my = (y1 + y2) / 2;
double radius = Math.sqrt(Math.pow(x1 - mx, 2)
+ Math.pow(y1 - my, 2));
circle=new Circle(mx,my,(int)radius);
invalidate();
}
}
And called method as
customView.drawCircleBetweenTwoPoints(500,200,100,600);
and its working for me
Click to see output
If you want to draw circle like this, you must know 3 points, then calculate center with radius. Because two points cannot uniquely determine a circle. You can find only whole line of possible centers.
On the other hand, if we consider that two points are exactly opposite. Then you should calculate center by midpoint formula:
M = [(x1 + x2 / 2), (y1 + y2 / 2)]
Next, you can do the same thing as at first case. First, calculate radius and then draw circle.
Assuming, that A and B are exactly opposite to each other, the line segment defined by them will pass through the centre of the circle (C), and the latter will cut AB in half.
Thus:
You calculate then distance of the two points, and divide by two. So you'll have the radius.
The centre of the circle will be exactly halfway between the two: x=(x1+x2)/2 and y=(y1+y2)/2.
If they happen to be just random points, you can use one of these techniques:
Link
Link
In this case however, your problem is slightly tricky, as two points and a radius will not determine one circle unambiguously: the problem will have two solutions.

Android Canvas OnDraw Touch Listener for Rotated Text

I have a Canvas Text is drawn using drawText Method with Rotation of -45 degree, what i need is a touch action for that Text part alone, the ref image is below,
My Code is below
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint newpaint=new Paint();
newpaint.setColor(Color.RED);
canvas.drawLine(10,10,getMeasuredWidth(),10,newpaint);
if(lines.size()>0)
{
Paint BluePaint=new Paint();
BluePaint.setColor(Color.BLUE);
BluePaint.setStrokeWidth(1.5f);
for (Line l : lines)
{
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY+50, BluePaint);
canvas.save();
canvas.rotate((float) (-45), l.startX, l.stopY+160);
canvas.drawText("Add Location",l.startX-10,l.stopY+90,BluePaint);
canvas.restore();
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
//Check if the x and y position of the touch is inside the bitmap
if( x > bitmapXPosition && x < bitmapXPosition + getMeasuredWidth() && y > bitmapYPosition && y < bitmapYPosition + 5 )
{
lines.add(new Line(event.getX(), event.getY()));
invalidate();
return true;
}
}
return false;
}
class Line {
float startX, startY, stopX, stopY;
public Line(float startX, float startY, float stopX, float stopY) {
this.startX = startX;
this.startY = startY;
this.stopX = stopX;
this.stopY = stopY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
I have detected the Line Touch event but, cannot be able to detect the touch event of the Text. Help to solve this.
First you need to apply the Affine transformation to the event.getX(),even.getY() point. Then check if the rectangle around the text contains this new transformed point as if it was not rotated.
Translating a point around some center:
Java: Rotate Point around another by specified degree value

Dynamically changing the rectangle size android

I'm making an application which can crop the image of the person. The layout of my application will give a better description
Here the rectangle will be used to capture the image defined by its length and width. The rectangle is movable. How would I go about re-sizing the rectangle. For eg. in WhatsApp when you touch the region inside the rectangle, the rectangle moves. If you touch the edges of rectangle, it provides the ability to re-size image suitable for cropping. So, I have 2 questions. 1) How to receive Touch events on edges of rectangle and 2) How would I re-size my rectangle. I'm using canvas to draw my rectangle. The code for this is as follows:
public class CustomView extends Views
{
public CustomView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);;
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(0, 0, 300, 300, paint);
}
}
You should implement the OnTouchListener and check in MotionEvent.ACTION_DOWN if you touch the rectangle and modify right, left, bottom and top of rectangle in MotionEvent.ACTION_MOVE
I provided a not tested example:
public class CustomView extends View {
private float left=0,right = 300, top = 0, bottom = 300;
public CustomView(Context context)
{
super(context);
setOnTouchListener( new OnTouchListener() {
float oldX, oldY;
#Override
public boolean onTouch(View v, MotionEvent event) {
boolean touch = false;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
touch = isTouchBorderRect();
break;
case MotionEvent.ACTION_UP:
touch = false;
case MotionEvent.ACTION_MOVE:
if (touch){
float newX = event.getRawX();
float newY = event.getRawY();
float deltaX = newX-oldX;
float deltaY = newY-oldY;
left-=deltaX;
right +=deltaX;
bottom += deltaY;
top -= deltaY;
}
break;
}
return false;
}
});
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);;
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(left, top, right, bottom, paint);
}
}
In isTouchBorderRect() method you should check if you have touched the rectangle.
This code is not tested but show the idea that you want to develop.

android line draw

I want to draw lines on the screen but my application is drawing only dotted. So what should I add in my code?
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
for (Point point : points) {
canvas.drawCircle(point.x, point.y, 5, paint);
// Log.d(TAG, "Painting: "+point);
}
}
public boolean onTouch(View view, MotionEvent event) {
// if(event.getAction() != MotionEvent.ACTION_DOWN)
// return super.onTouchEvent(event);
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d(TAG, "point: " + point);
return true;
}
}
class Point
{
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
Edit
Use drawLine or drawPath instead of drawCircle.
I would suggest you to take a look on the Fingerpaint example of the API Demos
Use drawLine bewteen 2 sets of points
For smoother lines, get all the historic events in onTouch and process them first
for faster/smoother, invalidate only the rect where points have changes
Read more here

how to get position(x and y coordinates) of circle drwan on canvas in android?

I have two doubts in canvas android.
They are explained below:
Firstly, I had drawn a row of circles on canvas, i want to capture the x and y coordinates of the circle(only on one circle)drawn so that I can draw a bitmap over the circle(in center).
Secondly, I want to imply touch event on circle i.e I want them to change color when some one touch them Can anybody help me with this?
for #2:
calculate the distance between the center of your point and the touch event - if the distance is smaller than the radius of your circle - you pressed on the circle
First you should create GridSector class for your "circle zone".
public class GridSector {
private int x = 0;
private int y = 0;
private Rect rect = new Rect(0, 0, 0, 0);
public GridSector(int x, int y, Rect rect) {
this.x = x;
this.y = y;
this.rect = rect;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Rect getRect() {
return rect;
}
public void setRect(Rect rect) {
this.rect.set(rect.left, rect.top, rect.right, rect.bottom);
}
}
Then Create view what you wanna touch.
public class GridSectorsView extends View {
GridSector currentSelectedSector;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircle(canvas); // draw your circles;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
invalidate(currentSelectedSector.getRect()); // update your circles (call onDraw Function ) ;
}
}
}

Categories

Resources