I want to display the coordinates of nodes which is placed on the view with the ontouch event, the coordinates are to be placed beside the circle nodes,temporarily i'm using (0,0) but i have no idea how to implement the real coordinates on the nodes properly,need some help.thanks
public class DrawView extends View implements OnTouchListener {
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
public DrawView(Draw context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
Paint rectanglePaint = new Paint();
rectanglePaint.setColor(Color.WHITE);
Paint layoutColor = new Paint();
layoutColor.setColor(Color.BLACK);
canvas.drawRect(new Rect(10,10,465,800), rectanglePaint);
canvas.drawLine(300, 10, 300, 800, layoutColor);
canvas.drawLine(0, 300, 465, 300, layoutColor);
// Paint textPaint = new Paint();
// textPaint.setColor(Color.CYAN);
// textPaint.setTextSize(30);
// canvas.drawText("Room", 220, 400, textPaint);
for (Point point : points) {
canvas.drawText("(0,0)", point.x+5, point.y+5, paint);
canvas.drawCircle(point.x, point.y, 5, paint);
// Log.d(TAG, "Painting: "+point);
}
}
final TextView textView = ( TextView )findViewById(R.id.textView1);
public boolean onTouch(View view, MotionEvent event) {
// return super.onTouchEvent(event);
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
return true;
}
}
Ahh, you don't really have a question about android. You have a java question. You want to know how to convert floats to strings.
This link will show you all you need to know: http://download.oracle.com/javase/tutorial/java/data/converting.html
String s = "(" + point.x + "," + point.y + ")";
Related
I'm making an app where user will be able to click on part of the image and get a magnified version in the corner of WebView. I managed to make a Paint that would make a zoom version, but it displays wrong location, like there's some offset.
I know this question has been asked a lot of times and was already answered, but it appears non of those solutions helped.
Here's code I've used:
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
zoomPos = new PointF();
zoomPos.x = event.getX();
zoomPos.y = event.getY();
matrix = new Matrix();
mShader = new BitmapShader(MainActivity.mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mShader);
outlinePaint = new Paint(Color.BLACK);
outlinePaint.setStyle(Paint.Style.STROKE);
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = true;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
Point1 = true;
zooming = false;
this.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
zooming = false;
this.invalidate();
break;
default:
break;
}
return true;
}
#Override
protected void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
if (zooming) {
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
mPaint.getShader().setLocalMatrix(matrix);
canvas.drawCircle(100, 100, 100, mPaint);
}
}
Technically it should draw a circle at upper-left corner and display zoomed image of area where my finger is, it draws a circle, but again, zoom is shifted.
Final result should look something like this:
MainActivity.java
public class MainActivity extends Activity {
static ImageView takenPhoto;
static PointF zoomPos;
Paint shaderPaint;
static BitmapShader mShader;
BitmapShader shader;
Bitmap bmp;
static Bitmap mutableBitmap;
static Matrix matrix;
Canvas canvas;
static Paint mPaint;
static Paint Paint;
static boolean zooming;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File file = new File(Environment.getExternalStorageDirectory() + "/Pictures/boxes.jpg");
String fileString = file.getPath();
takenPhoto = (ZoomView) findViewById(R.id.imageView1);
bmp = BitmapFactory.decodeFile(fileString);
mutableBitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
takenPhoto.setImageBitmap(mutableBitmap);
matrix = new Matrix();
mShader = new BitmapShader(mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mShader);
zoomPos = new PointF();
Paint = new Paint(Color.RED);
}
}
ZoomView.java
public class ZoomView extends ImageView {
private PointF zoomPos;
PointF fingerPos;
private Paint paint = new Paint(Color.BLACK);
boolean zooming;
Matrix matrix;
BitmapShader mShader;
Paint mPaint;
Paint outlinePaint;
boolean Point1;
public ZoomView(Context context) {
super(context);
}
public ZoomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZoomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
zoomPos = new PointF();
zoomPos.x = event.getX();
zoomPos.y = event.getY();
matrix = new Matrix();
mShader = new BitmapShader(MainActivity.mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mShader);
outlinePaint = new Paint(Color.BLACK);
outlinePaint.setStyle(Paint.Style.STROKE);
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = true;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
Point1 = true;
zooming = false;
this.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
zooming = false;
this.invalidate();
break;
default:
break;
}
return true;
}
#Override
protected void onDraw(#NonNull Canvas canvas) {
super.onDraw(canvas);
if (zooming) {
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
mPaint.getShader().setLocalMatrix(matrix);
RectF src = new RectF(zoomPos.x-50, zoomPos.y-50, zoomPos.x+50, zoomPos.y+50);
RectF dst = new RectF(0, 0, 100, 100);
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
matrix.postScale(2f, 2f);
mPaint.getShader().setLocalMatrix(matrix);
canvas.drawCircle(100, 100, 100, mPaint);
canvas.drawCircle(zoomPos.x, zoomPos.y, 100, mPaint);
canvas.drawCircle(zoomPos.x-110, zoomPos.y-110, 10, outlinePaint);
}
if(Point1){
canvas.drawCircle(zoomPos.x, zoomPos.y, 10, paint);
}
}
}
EDIT:
As you can see new code is way better, still there is some offset - black dot - position of the finger.
Seems that the issue is with how you are using the matrix.
Now you are using the original image (1) as a shader which is then being post scaled up around a pivot point (2), which is like doing a zoom around a point (3) - but not centering the point (4) ! (For example, open google maps and zoom in on the map with your mouse - the point is zoomed around the pivot but the pivot is not centered)
What will be an easier way to achieve what you want is by using the Rect to Rect method. I.E. you want to take a small area from the original image (5) and draw it to a larger area (6) .
And here is a code sample:
RectF src = new RectF(zoomPos.x-50, zoomPos.y-50, zoomPos.x+50, zoomPos.y+50);
RectF dst = new RectF(0, 0, 200, 200);
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
Some more points:
Try not to create new object in the onTouch - it is being called many times and it is not good on performance . Instead, create once and reuse.
getAction() will have issues when there are more than one finger on screen since it is the action ID and the pointer ID. Instead use getActionMasked() and getActionIndex().
Do not use hardcoded values (50/100 in the sample code) - these are pixels and are not aware of screen density. Use scaled size like dp.
İn my application İ want to make a ball move inside a specific area (rectangle). till now the ball moves all around the screen in the background area under the rectangle. İ tried changing the coordinates several time but it didnt work. can anyone help me make the ball move within the rectangle?
class DrawView extends View {
int x,y,x1,y1;
int a=431,b=641, a1=54,b1=54;
int sayac=0;
Canvas can;
Paint paint = new Paint();
Rect r = new Rect(60, 60, 400, 610);
Paint por= new Paint();
// Font bold;
public DrawView(Context context) {
super(context);
paint.setColor(Color.RED);
}
private void update() {
if(a>605){x=-(int)(Math.random()*7+5); }
if(a<55){x=(int)(Math.random()*7+5); }
if(b>395){y=-(int)(Math.random()*7+5); }
if(b<55){y=(int)(Math.random()*7+5); }
if(a1>605){x1=-(int)(Math.random()*7+5); }
if(a1<55){x1=(int)(Math.random()*7+5); }
if(b1>395){y1=-(int)(Math.random()*7+5); }
if(b1<55){y1=(int)(Math.random()*7+5); }
a+=x;
b+=y;
a1+=x1;
b1+=y1;
}
#Override
protected void onDraw(Canvas canvas) {
paint.setTextSize(20);
paint.setColor(Color.YELLOW);
canvas.drawCircle(a, b, 50, paint);
paint.setColor(Color.BLUE);
canvas.drawText("Pamukcu", a-41, b+7, paint);
/* paint.setColor(Color.RED);
canvas.drawLine(40, 40, 600, 40, paint);
paint.setStrokeWidth(10f);
canvas.drawLine(40, 600, 600, 600, paint);
canvas.drawLine(40, 40, 40, 600, paint);
canvas.drawLine(600, 40, 40, 600, paint);
*/
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.MAGENTA);
canvas.drawRect(r, paint);
update();
try{
Thread.sleep(1);
}catch(InterruptedException e){ }
invalidate();
private void update() {
if(a>605){x=-(int)(Math.random()*7+5); }
if(a<55){x=(int)(Math.random()*7+5); }
if(b>395){y=-(int)(Math.random()*7+5); }
if(b<55){y=(int)(Math.random()*7+5); }
if(a1>605){x1=-(int)(Math.random()*7+5); }
if(a1<55){x1=(int)(Math.random()*7+5); }
if(b1>395){y1=-(int)(Math.random()*7+5); }
if(b1<55){y1=(int)(Math.random()*7+5); }
a+=x;
b+=y;
a1+=x1;
b1+=y1;
}
#Override
protected void onDraw(Canvas canvas) {
paint.setTextSize(20);
paint.setColor(Color.YELLOW);
canvas.drawCircle(a, b, 50, paint);
paint.setColor(Color.BLUE);
canvas.drawText("Ball", a-41, b+7, paint);
If you want that the ball can only move inside a rectangle than you can do it like this:
int rectangleX = 100;
int rectangleY = 100;
int rectangleWidht = 200;
int rectangleHeight = 300;
private void KeepBallInsideRectangle() {
if (ballX < rectanlgeX) ballX = rectangleX;
if (ballX > rectangleX+rectangleWidth) ballX = rectangleX+rectangleWidth;
if (ballY < rectanlgeY) ballY = rectangleY;
if (ballY > rectangleY+rectanglHeight) ballY = rectangleY+rectangleHeight;
}
You just check if the balls position is outside of the rectangle and then set its position to the border of the rectangle.
I have the following app which allows a circle to be drawn on touch. When the screen is touched a second time the first touch circle is removed and a new circle is created where the second touch occurs. How can allow multiple circles to appear for as many times the screen is touched?(i.e. 5 touch events = 5 circles appear on the same canvas in their touch locations).
public class Lab12Activity extends Activity {
Point pt = new Point();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends View implements View.OnTouchListener {
public DrawView(Context context) {
super(context);
this.setOnTouchListener(this);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
canvas.drawCircle(pt.x, pt.y, 15, paint);
paint.setColor(Color.BLUE);
canvas.drawRect(0, 0, 225, 150, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
paint.setColor(Color.WHITE);
paint.setTextSize(30);
canvas.drawText("Clear", 75, 75, paint);
canvas .drawText("Tap to add Circles", 300, 75, paint);
}
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
pt.x = (int) event.getX();
pt.y = (int) event.getY();
invalidate();
}
return true;
}
}
}
use event.getActionIndex (); it returns the pointer index of the touch event.
Here is the code of a simple extension of an ImageView that allow the user to draw with the finger.
public class MyImageView extends ImageView {
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onDraw(Canvas canvas) {
for (Point point : points) {
canvas.drawCircle(point.x, point.y, 5, paint);
// Log.d(TAG, "Painting: "+point);
}
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d("", "point: " + point);
return true;
}
class Point {
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
}
This work pretty well.
Now, I want to use this code to draw at the top of a Bitmap.
I used:
MyImageView ivPic = (MyImageView) dialog.findViewById(R.id.ivPic);
ivPic.setImageBitmap(picture);
But the drawing is drawn "behind" the Bitmap:
Do you have any idea how I can draw at the "top" of the Bitmap?
I've changed the order in onDraw method, I put super.onDraw(canvas); at the beginning and I think it works now
override and use dispatchDraw Method, i used it to draw over views
I answer my own question, just found the answer:
ivPic.setBackgroundDrawable(new BitmapDrawable(getResources(),picture));
Don't know if that's the best practice but that works for me...
Change the sequence: first super.OnDraw(canvas) then your paint stuff
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Point point : points) {
canvas.drawCircle(point.x, point.y, 5, paint);
// Log.d(TAG, "Painting: "+point);
}
}
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