I am using an ImageView to create a canvas and draw elements with finger touch on it. But the problem is that, firstly the canvas only covers a little portion of the screen to draw or write something and secondly it produces lines or curves far away where I touch. I have one textview and the imageview in linear layout. Please check my code and help me for the same.
DrawTestActivity.java:
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class MainActivity extends Activity implements OnTouchListener {
ImageView imageView;
Bitmap bitmap;
Canvas canvas;
Path path;
Paint paint;
float downx = 0, downy = 0, upx = 0, upy = 0;
float startX = 0;
float startY = 0;
float endX = 0;
float endY = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) this.findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
imageView.setImageBitmap(bitmap);
imageView.setOnTouchListener(this);
}
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
startX=event.getX();
startY=event.getY();
break;
case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getY();
canvas.drawLine(startX,startY,endX,endY, paint);
imageView.invalidate();
startX=endX;
startY=endY;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
}
Related
I have a custom view in my project. In the view class I draw a line using onDraw method. The height of the line can be changed by swiping up and down.How can I set a max and min value for the height of that line?
This is my code
package com.example.richyrony.draw;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
/**
* Created by Richy & Rony on 26-01-2018.
*/
public class Line extends View {
PointF topLeft = new PointF(100, 100);
PointF topRight = new PointF(290, 100);
PointF bottomLeft = new PointF(100, 290);
PointF bottomRight = new PointF(290, 290);
private final int NONE = -1, TOUCH_TOP_LEFT = 0, TOUCH_TOP_RIGHT = 1, TOUCH_BOT_LEFT = 2, TOUCH_BOT_RIGHT = 3;
int currentTouch = NONE;
Float lineTwoStartx = 250f;
Float lineTwoStart = 50f;
Float lineTwoEndx = 250f;
Float lineTwoEnd = 200f;
Float lineOneStartx = 50f;
Float lineOneStart = 50f;
;
Float lineOneEndx = 50f;
Float lineOneEnd = 200f;
RectF touchArea = new RectF(0, 0, 350, 350);
Paint paint;
public Line(Context context) {
super(context);
paint = new Paint();
paint.setStrokeWidth(4);
paint.setColor(Color.parseColor("#000000"));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(lineOneStartx, lineOneStart, lineOneEndx, lineOneEnd, paint);
canvas.drawLine(lineTwoStartx, lineTwoStart, lineTwoEndx, lineTwoEnd, paint);
canvas.drawLine(lineOneEndx, lineOneEnd, lineTwoEndx, lineTwoEnd, paint);
canvas.drawLine(lineOneStartx, lineOneStart, lineTwoStartx, lineTwoStart, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//The user just put their finger down.
//We check to see which corner the user is touching
//And set our global, currentTouch, to the appropriate constant.
case MotionEvent.ACTION_DOWN:
if (touchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_TOP_LEFT;
Toast.makeText(getContext(), "tf" + currentTouch, Toast.LENGTH_SHORT).show();
} else {
return false; //Return false if user touches none of the corners
}
return true; //Return true if the user touches one of the corners
//Now we know which corner the user is touching.
//When the user moves their finger, we update the point to the user position and invalidate.
case MotionEvent.ACTION_MOVE:
switch (currentTouch) {
case TOUCH_TOP_LEFT:
lineOneEnd = event.getY();
invalidate();
return true;
}
//We returned true for all of the above cases, because we used the event
return false; //If currentTouch is none of the above cases, return false
//Here the user lifts up their finger.
//We update the points one last time, and set currentTouch to NONE.
case MotionEvent.ACTION_UP:
switch (currentTouch) {
case TOUCH_TOP_LEFT:
lineOneEnd = event.getY();
currentTouch = NONE;
invalidate();
return true;
}
return false;
}
return false;
}
}
And also if anyone has any idea on how to measure angles between two lines it would be helpful
hey i am trying to create android app where i can draw on canvas with two buttons on the bottom
i managed to get the drawing to work however right now i need to add two buttons(one is for saving the drawing canvas into database (Sqlite if possible) or bitmap and the other one to import the image from the sqlite and display it into the graphicview)
right now i have no idea what code i have to put into it to make the save and display button works so please help me with the code and thank you for your time :)
here is my code at the moment (the graphic drawing works fine and now i need the code for the save and display button as well as what ive missed in the graphicview.java and MainActivity.java)
GraphicsView.java
package org.example.graphics;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Path.Direction;
import android.view.*;
public class GraphicsView extends View implements View.OnTouchListener {
public GraphicsView(Context context) {
super(context);
setBackgroundColor(Color.WHITE);
setOnTouchListener(this);
}
ArrayList<MyPoint> arrOfPoints=new ArrayList<MyPoint>();
class MyPoint
{
float x, y;
}
float downx, downy;
#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
Paint rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectPaint.setStyle(Paint.Style.FILL_AND_STROKE);
rectPaint.setColor(Color.BLACK);
canvas.drawRoundRect(new RectF(0, 0, 100, 100), 10, 10, rectPaint);
rectPaint.setColor(Color.BLUE);
rectPaint.setAlpha(40);
canvas.drawCircle(300, 300, 200, rectPaint);
canvas.drawRect(new RectF(40, 40, 200, 200), rectPaint);
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG
| Paint.STRIKE_THRU_TEXT_FLAG);
canvas.drawText("Hello there!", 200, 200, textPaint);
canvas.drawText("You clicked on " + downx + "," + downy, 200, 600,
textPaint);
for(int i=0;i<arrOfPoints.size();i++)
{
canvas.drawCircle(arrOfPoints.get(i).x, arrOfPoints.get(i).y, 20, rectPaint);
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
int action = arg1.getAction();
MyPoint p=null;
switch (action) {
case MotionEvent.ACTION_DOWN:
downx = arg1.getX();
downy = arg1.getY();
p=new MyPoint();
p.x=arg1.getX();p.y=arg1.getY();
arrOfPoints.add(p);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
downx = arg1.getX();
downy = arg1.getY();
p=new MyPoint();
p.x=arg1.getX();p.y=arg1.getY();
arrOfPoints.add(p);
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
MainActivity.java
package org.example.graphics;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GraphicsView(this));
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background">
<org.example.graphics.GraphicsView
android:id="#+id/graphics"
android:layout_width="fill_parent"
android:layout_height="341dp" />
<Button
android:id="#+id/ChoosePictureButton"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Choose Picture"
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Save Picture" android:id="#+id/SavePictureButton"/>
</LinearLayout>
My AndroidManifest.xml is still at default because i havent edit anything in it yet
You can use this code in your save button click listener.
int canvasWidth = 500;
int canvasHeight = 500;
View v = new GraphicsView(MainActivity.this);
Bitmap bitmap = Bitmap.createBitmap(canvasWidth, canvasHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
//now bitmap has your canvas image
//set it to your ImageView
yourImageView.setImageBitmap(bitmap);
//or save to sdcard
File dir = new File("/sdcard/yourAppFolder/");
if (!dir.isDirectory()) {
dir.mkdirs();
}
File outputFile = new File(dir, "image.jpg");
OutputStream fout = null;
fout = new FileOutputStream(outputFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
fout.flush();
fout.close();
I have two images, one above one and i want to make the upper image transparent when user erase it and covered image should be shown...hear is my code
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
public class StartActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchView(this));
}
class TouchView extends View{
Bitmap bgr;
Bitmap overlayDefault;
Bitmap overlay;
Paint pTouch;
int X = -100;
int Y = -100;
Canvas c2;
public TouchView(Context context) {
super(context);
bgr = BitmapFactory.decodeResource(getResources(),R.drawable.bgr);
overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.over);
overlay = BitmapFactory.decodeResource(getResources(),R.drawable.over).copy(Config.ARGB_8888, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
break;
}
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//draw background
canvas.drawBitmap(bgr, 0, 0, null);
//copy the default overlay into temporary overlay and punch a hole in it
c2.drawBitmap(overlayDefault, 0, 0, null); //exclude this line to show all as you draw
c2.drawCircle(X, Y, 80, pTouch);
//draw the overlay over the background
canvas.drawBitmap(overlay, 0, 0, null);
}
}
}
But I am getting error at line:
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
The error is:
"SRC_OUT cannot be resolved or is not a field".
Close, you need to ensure your Mode is from the correct package. What you should use is:
android.graphics.PorterDuff.Mode
Changing the problem line to:
pTouch.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
I need to draw a Bitmap on a canvas but I need to remove the black pixels to transparent. Is there an easy way to do this in Android? Bitmap.clearColor seems to behave differently.
Check to make sure the overlay bitmap you've created is actually transparent. Create it with config ARGB_8888 explicitly. http://developer.android.com/reference/android/graphics/Bitmap.Config.html
And you might want to move the creation of the bitmap out of the reDraw method and only create it once instead.
it will works on on touch
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
public class StartActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchView(this));
}
class TouchView extends View{
Bitmap bgr;
Bitmap overlayDefault;
Bitmap overlay;
Paint pTouch;
int X = -100;
int Y = -100;
Canvas c2;
public TouchView(Context context) {
super(context);
bgr = BitmapFactory.decodeResource(getResources(),R.drawable.bgr);
overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.over);
overlay = BitmapFactory.decodeResource(getResources(),R.drawable.over).copy(Config.ARGB_8888, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_UP:
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
//draw background
canvas.drawBitmap(bgr, 0, 0, null);
//copy the default overlay into temporary overlay and punch a hole in it
c2.drawBitmap(overlayDefault, 0, 0, null); //exclude this line to show all as you draw
c2.drawCircle(X, Y, 80, pTouch);
//draw the overlay over the background
canvas.drawBitmap(overlay, 0, 0, null);
}
}
}`
Check this answer. It's not accepted but should work. Dont forget to turn of hardware acceleration for view where you use this bitmap.
I need to draw a circle as per my finger move so i have write this code
package com.sport;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class sport extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchView(this));
}
class TouchView extends View {
Bitmap bgr;
Bitmap overlayDefault;
Bitmap overlay;
Paint pTouch;
int X;
int Y;
Canvas c2;
public TouchView(Context context) {
super(context);
bgr = BitmapFactory.decodeResource(getResources(), R.drawable.new1);
overlayDefault = BitmapFactory.decodeResource(getResources(),
R.drawable.original);
overlay = BitmapFactory.decodeResource(getResources(),
R.drawable.new1).copy(Config.ARGB_8888, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.DEV_KERN_TEXT_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
pTouch.setColor(Color.TRANSPARENT);
// pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int ht = displaymetrics.heightPixels;
int wt = displaymetrics.widthPixels;
X = wt / 2;
Y = 0;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
//invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
/* Toast.makeText(getBaseContext(),"x is::"+ X,
Toast.LENGTH_LONG).show();
Toast.makeText(getBaseContext(),"Y is::"+ Y,
Toast.LENGTH_LONG).show();*/
//c2.drawCircle(X, Y, 70, pTouch);
/*System.out.println("x is"+X);
System.out.println("Y is"+Y);*/
invalidate();
break;
}
case MotionEvent.ACTION_UP:
X = (int) ev.getX();
Y = (int) ev.getY();
/*
* Toast.makeText(getBaseContext(),"x is::"+ X,
* Toast.LENGTH_LONG).show();
* Toast.makeText(getBaseContext(),"Y is::"+ Y,
* Toast.LENGTH_LONG).show();
*/
//invalidate();
break;
case MotionEvent.ACTION_POINTER_ID_MASK :
/*X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();*/
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int ht = displaymetrics.heightPixels;
int wt = displaymetrics.widthPixels;
int heightbitmap = bgr.getHeight();
int widthbitmap = bgr.getWidth();
int minus = wt - widthbitmap;
// draw background
canvas.drawBitmap(bgr, minus / 2, 0, null);
// copy the default overlay into temporary overlay and punch a hole
// in it
c2.drawBitmap(overlayDefault, 360, 0, null); // exclude this line to
// show all as you
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.diff_6); // draw
//c2.drawBitmap(_scratch, 10, 10, pTouch);
if(X >= 470 & X <= 522)
{
if(Y >= 255 & Y<= 330)
{
//c2.drawRect(X, Y, 5, 5, pTouch);
double outer_radius = 0.5 * Math.sqrt((_scratch.getWidth()) * (_scratch.getWidth())+ (_scratch.getHeight()) * (_scratch.getHeight()));
float f = (float) outer_radius;
c2.drawCircle(X, Y, f, pTouch);
}
}
// draw the overlay over the background
canvas.drawBitmap(overlay, minus/2, 0, null);
}
}
}
Problem::
when i touch on screen circle are stay at right side of my finger Like this.
but i need it center of my finger please help on this
The problem is because you create 'overlay' with respect to the x and y cordinates from the touch event and later copying this onto the background with an offset (minus/2). Assuming your background image is smaller than the screen resolution the circle will always shift right and hence will look the circle is at the right of your finger.
If you use a background image which has same resolution as the screen dimensions , you will get properly drawn circle, with its centre at the point of touch.