How to draw a path on an Android canvas with animation? - android

I'm making an Android app and I've got a tricky thing to do.
I need to draw a path on a canvas but the drawing should be animated (ie. drawing point after point with a slight delay).
Is it possible to make something like this using Android SDK?
If not, how could I produce this effect?

Try this code, I used it to draw a heartbeat using Path & Canvas:
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new HeartbeatView(this));
}
public static class HeartbeatView extends View {
private static Paint paint;
private int screenW, screenH;
private float X, Y;
private Path path;
private float initialScreenW;
private float initialX, plusX;
private float TX;
private boolean translate;
private int flash;
private Context context;
public HeartbeatView(Context context) {
super(context);
this.context=context;
paint = new Paint();
paint.setColor(Color.argb(0xff, 0x99, 0x00, 0x00));
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStyle(Paint.Style.STROKE);
paint.setShadowLayer(7, 0, 0, Color.RED);
path= new Path();
TX=0;
translate=false;
flash=0;
}
#Override
public void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenW = w;
screenH = h;
X = 0;
Y = (screenH/2)+(screenH/4)+(screenH/10);
initialScreenW=screenW;
initialX=((screenW/2)+(screenW/4));
plusX=(screenW/24);
path.moveTo(X, Y);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.save();
flash+=1;
if(flash<10 || (flash>20 && flash<30))
{
paint.setStrokeWidth(16);
paint.setColor(Color.RED);
paint.setShadowLayer(12, 0, 0, Color.RED);
}
else
{
paint.setStrokeWidth(10);
paint.setColor(Color.argb(0xff, 0x99, 0x00, 0x00));
paint.setShadowLayer(7, 0, 0, Color.RED);
}
if(flash==100)
{
flash=0;
}
path.lineTo(X,Y);
canvas.translate(-TX, 0);
if(translate==true)
{
TX+=4;
}
if(X<initialX)
{
X+=8;
}
else
{
if(X<initialX+plusX)
{
X+=2;
Y-=8;
}
else
{
if(X<initialX+(plusX*2))
{
X+=2;
Y+=14;
}
else
{
if(X<initialX+(plusX*3))
{
X+=2;
Y-=12;
}
else
{
if(X<initialX+(plusX*4))
{
X+=2;
Y+=6;
}
else
{
if(X<initialScreenW)
{
X+=8;
}
else
{
translate=true;
initialX=initialX+initialScreenW;
}
}
}
}
}
}
canvas.drawPath(path, paint);
//canvas.restore();
invalidate();
}
}
}
It uses drawing a Path point by point with couple of effects using counters. You can take what you need and transfer it to SurfaceView which is more efficient.

I hope this is what you are looking for. It draws the path on user touch, you could simply tweek it to achieve what you desire.
public class MyCanvas extends Activity implements OnTouchListener{
DrawPanel dp;
private ArrayList<Path> pointsToDraw = new ArrayList<Path>();
private Paint mPaint;
Path path;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
dp = new DrawPanel(this);
dp.setOnTouchListener(this);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(30);
FrameLayout fl = new FrameLayout(this);
fl.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
fl.addView(dp);
setContentView(fl);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
dp.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
dp.resume();
}
public class DrawPanel extends SurfaceView implements Runnable{
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false ;
public DrawPanel(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
}
#Override
public void run() {
// TODO Auto-generated method stub
while( isItOk == true){
if(!holder.getSurface().isValid()){
continue;
}
Canvas c = holder.lockCanvas();
c.drawARGB(255, 0, 0, 0);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
synchronized(pointsToDraw)
{
for (Path path : pointsToDraw) {
canvas.drawPath(path, mPaint);
}
}
}
public void pause(){
isItOk = false;
while(true){
try{
t.join();
}catch(InterruptedException e){
e.printStackTrace();
}
break;
}
t = null;
}
public void resume(){
isItOk = true;
t = new Thread(this);
t.start();
}
}
#Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
synchronized(pointsToDraw)
{
if(me.getAction() == MotionEvent.ACTION_DOWN){
path = new Path();
path.moveTo(me.getX(), me.getY());
//path.lineTo(me.getX(), me.getY());
pointsToDraw.add(path);
}else if(me.getAction() == MotionEvent.ACTION_MOVE){
path.lineTo(me.getX(), me.getY());
}else if(me.getAction() == MotionEvent.ACTION_UP){
//path.lineTo(me.getX(), me.getY());
}
}
return true;
}
}

I have made it with ObjectAnimator.
We have any Path and our CustomView (in wich we'll draw our path)
private CustomView view;
private Path path;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = findViewById(R.id.custom_view);
path = new Path();
path.moveTo(0f, 0f);
path.lineTo(getResources().getDimension(R.dimen.point_250), 0f);
path.lineTo(getResources().getDimension(R.dimen.point_250), getResources().getDimension(R.dimen.point_150));
findViewById(R.id.btnStart).setOnClickListener(v -> {
test();
});
}
private void test() {
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "xCoord", "yCoord", path);
pathAnimator.setDuration(5000);
pathAnimator.start();
}
And just pass our "xCoord" and "yCoord" to CustomView
public class CustomView extends View {
private Paint paint;
private float xCoord;
private float yCoord;
private Path path = new Path();
public void setXCoord(float xCoord) {
this.xCoord = xCoord;
}
public void setYCoord(float yCoord) {
this.yCoord = yCoord;
path.lineTo(xCoord, yCoord);
invalidate();
}
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(20);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
}
}

This might help... It draws adjacent circles instead of a path to simulate an animatable path.
public class PathAnimatable {
private final float CIRCLE_SIZE = 2.5f;
public float SPPED_SCALE = 1f;
private float steps = 0;
private float pathLength;
private PathMeasure pathMeasure;
private float totalStepsNeeded;
private float[] point = new float[]{0f, 0f};
private float stride;
public PathAnimatable() {
this(null);
}
public PathAnimatable(Path path) {
super(path);
init();
}
private void init() {
pathMeasure = new PathMeasure(path, false);
pathLength = pathMeasure.getLength();
stride = CIRCLE_SIZE * 0.5f;
totalStepsNeeded = pathLength / stride;
steps = 0;
}
#Override
public void setPath(Path path) {
super.setPath(path);
init();
}
// Called this from your locked canvas loop function
public void drawShape(Canvas canvas, Paint paint) {
if (steps <= pathLength) {
for (float i = 0; i < steps ; i += stride) {
pathMeasure.getPosTan(i, point, null);
canvas.drawCircle(point[0], point[1], CIRCLE_SIZE, paint);
}
steps += stride * SPPED_SCALE;
} else {
steps = 0;
}
}
}

Related

PorterDuff.Mode.CLEAR draws black on canvas

I want to implement eraser in my paint app. But the code
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
draws black line on canvas. If I am changing the background color the canvas draws black on it too.
I have also tried using setLayerType() but it draws white on any color background.
// In constructor
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Below is the code for my PaintView.
public class PaintView extends View {
private Bitmap bitmapBackground,bitmapView;
private int backgroundColor;
private int brushSize;
private int eraserSize;
private float mX,mY;
private Canvas canvas=null;
private final int TOUCH_TOLERANCE=4;
private int paintColor;
private int modeStatus;
/*
1 for brush
2 for eraser
*/
private ArrayList<Paint> paints = new ArrayList<>();
private ArrayList<Path> paths = new ArrayList<>();
private int historyPointer=0;
public PaintView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
initialise();
}
private void initialise() {
eraserSize=12;
brushSize=12;
backgroundColor= Color.WHITE;
paintColor = Color.BLACK;
modeStatus = 1;
paints.add(createPaint());
paths.add(new Path());
historyPointer++;
}
private float toPx(int brushSize) {
return brushSize*(getResources().getDisplayMetrics().density);
}
public void init(int width,int height) {
bitmapBackground=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
bitmapView=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
canvas=new Canvas(bitmapView);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(backgroundColor);
canvas.drawBitmap(bitmapBackground,0,0,null);
for (int i=0;i<historyPointer;i++) {
Path path = paths.get(i);
Paint paint = paints.get(i);
canvas.drawPath(path,paint);
}
}
private Paint createPaint() {
Paint paint = new Paint();
paint.setColor(paintColor);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
if (modeStatus==1) {
paint.setXfermode(null);
paint.setShader(null);
paint.setMaskFilter(null);
paint.setStrokeWidth(toPx(brushSize));
}
else {
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
paint.setStrokeWidth(toPx(eraserSize));
}
return paint;
}
private Path createPath(float x,float y) {
Path path = new Path();
path.moveTo(x,y);
return path;
}
public void setBackgroundColor(int backgroundColor) {
this.backgroundColor=backgroundColor;
invalidate(); //Redraw
}
public void setBrushSize(int brushSize) {
this.brushSize=brushSize;
modeStatus=1;
}
public void setBrushColor(int color) {
paintColor=color;
}
public void setEraserSize(int eraserSize) {
this.eraserSize=eraserSize;
modeStatus=2;
}
public int getBrushSize() {
return this.brushSize;
}
public int getEraserSize() {
return this.eraserSize;
}
private void updateHistory(Path path) {
if (historyPointer==paths.size()) {
paths.add(path);
paints.add(createPaint());
historyPointer++;
}
else {
// For undo and redo
paths.set(historyPointer,path);
paints.set(historyPointer,createPaint());
historyPointer++;
for (int i=historyPointer,size=paths.size();i<size;i++) {
paths.remove(historyPointer);
paints.remove(historyPointer);
}
}
}
private Path getCurrentPath() {
return paths.get(historyPointer-1);
}
private Paint getCurrentPaint() {
return paints.get(historyPointer-1);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
// Case when finger touches the screen
case MotionEvent.ACTION_DOWN:
touchStart(x,y);
break;
// Case when finger moves on screen
case MotionEvent.ACTION_MOVE:
touchMove(x,y);
break;
// Case when finger is taken away from screen
case MotionEvent.ACTION_UP:
touchUp();
break;
default :
return false;
}
return true;
}
private void touchStart(float x, float y) {
mX=x;
mY=y;
updateHistory(createPath(x,y));
}
private void touchMove(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
Path path = getCurrentPath();
if (dx>=TOUCH_TOLERANCE || dy>=TOUCH_TOLERANCE) {
path.quadTo(x,y,(x+mX)/2,(y+mY)/2);
mX=x;
mY=y;
}
invalidate();;
}
private void touchUp() {
}
}
I got the answer after many research and the following worked.
Just save the canvas layer after setting the background color and at last restore to count.
The onDraw method is as follows -
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(backgroundColor);
canvas.drawBitmap(bitmapBackground,0,0,null);
int layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); // Line 1 added
for (int i=0;i<historyPointer;i++) {
Path path = paths.get(i);
Paint paint = paints.get(i);
canvas.drawPath(path,paint);
}
canvas.restoreToCount(layerId); // Line 2 added
}

How to Draw line with different color and size?

When i choose initially red and draw a line, and then later select blue and draw a line , now the older line is also getting changed to blue instead of red, However i want the red to remain as red, and blue as such can any one help?
I also tried to get this solution online bt not solve my problem.so please help me.
DrawingView.java
public class DrawingView extends View {
Paint mPaint;
Path mpath;
Canvas mCanvas;
Bitmap myBitmap;
//initial color
private int paintColor = 0xFF660000;
private ArrayList<PathWithPaint> _graphics1 = new ArrayList<PathWithPaint>();
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
// private Map<Path,Float> stoWid = new HashMap<Path,Float>();
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
Drawingsetup();
}
private void Drawingsetup() {
// TODO Auto-generated method stub
mPaint = new Paint();
mpath = new Path();
mCanvas = new Canvas();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFFFF);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.BEVEL);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
myBitmap = Bitmap.createBitmap(820, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(myBitmap);
mCanvas.drawBitmap(myBitmap, 20, 20, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//return super.onTouchEvent(event);
PathWithPaint pp = new PathWithPaint();
//mCanvas.drawPath(path, mPaint);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
undonePaths.clear();
mpath.moveTo(event.getX(), event.getY());
mpath.lineTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
mpath.lineTo(event.getX(), event.getY());
pp.setPath(mpath);
pp.setmPaint(mPaint);
_graphics1.add(pp);
} else if (event.getAction()==MotionEvent.ACTION_UP) {
mpath.lineTo(event.getX(), event.getY());
// commit the path to our offscreen
mCanvas.drawPath(mpath, mPaint);
// kill this so we don't double draw
paths.add(mpath);
mpath = new Path();
colorsMap.put(mpath,paintColor); // store the color of mPath
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//canvas.drawBitmap(myBitmap, 0, 0, mPaint);
for(Path p: paths){
canvas.drawPath(p, mPaint);
mPaint.setColor(colorsMap.get(p));
}
canvas.drawPath(mpath, mPaint);
canvas.setColor(paintColor);
}
public void CurrentDraw(){
}
public void StartNew(){
//colorsMap.clear();
undonePaths.clear();
paths.clear();
myBitmap.eraseColor(Color.TRANSPARENT);
mpath.reset();
invalidate();
_graphics1.clear();
}
public void ColorChanged(String newColor){
//set color
// start by invalidating the View
//parse and set the color for drawing
paintColor = Color.parseColor(newColor);
mPaint.setColor(paintColor);
invalidate();
}
public void onClickUndo()
{
if (paths.size()>0) {
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
}
}
public void onClickRedo (){
if (undonePaths.size()>0) {
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
}
}
DrawingActivity.java
public class DrwaingActivity extends Activity {
DrawingView drawView;
Bitmap myBitmap;
private ImageButton currentpaint ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_image);
//get drawing view
drawView = (DrawingView)findViewById(R.id.drawing);
// drawView.setOnClickListener(this);
//get the palette and first color button
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currentpaint = (ImageButton)paintLayout.getChildAt(0);
currentpaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_item, menu);
return true;
}
public void paintClicked(View view){
if(view!=currentpaint)
{
//update color
// retrieve the tag we set for each button in the layout, representing the chosen color
ImageButton imgView = (ImageButton)view;
String color = view.getTag().toString();
// call the new method on the custom drawing View object
drawView.ColorChanged(color);
// update the UI to reflect the new chosen paint and set the previous one back to normal
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currentpaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currentpaint=(ImageButton)view;
}
}

Change the color of line draw line android

I'm using this app to draw free lines in android
DrawerView.java
public class DrawerView extends View {
public static Paint paint;
Paint paint2 = new Paint();
public Path path = new Path();
public Path circlePath = new Path();
public static int lineCol = Color.BLUE;
public static boolean isTouchable = false;
public LayoutParams params;
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(lineCol);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
}
public void onButtonPress(){
// resets the screen
path.reset();
// Calls the onDraw() method
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isTouchable){
return false;
} else {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
circlePath.reset();
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
postInvalidate();
return true;
}
}
}
DrawLines.java
public class DrawLines extends Activity {
DrawerView myView;
public Button btnReset;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_line);
myView = (DrawerView)findViewById(R.id.custView);
btnReset = (Button) findViewById(R.id.button1);
btnReset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// resets the screen
myView.path.reset();
// Calls the onDraw() method
myView.postInvalidate();
}
});
}
}
draw_line.xml
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Clear" />
<com.example.drawline.DrawerView
android:id="#+id/custView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/button1"
android:layout_margin="5dp"
custom:lineColor="#ff0099" />
It works well with me but I want to be able to select the color of line, so I added a button in draw_line.xml that when press it show a dialog that asks the user to select color. this is the code of dialog
public void openSelectColorDialog()
{
final Dialog d = new Dialog(this);
d.setTitle("Select Color");
d.setContentView(R.layout.military_list);
int image[] = { R.drawable.black, R.drawable.blue, R.drawable.yellow};
ArrayList<HashMap<String, String>> objArayList = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < image.length; i++) {
HashMap<String, String> listData = new HashMap<String, String>();
listData.put("image", Integer.toString(image[i]));
objArayList.add(listData);
}
String[] from = { "image"};
int[] to = { R.id.list_image };
SimpleAdapter listAdapter = new SimpleAdapter(this, objArayList,
R.layout.military_list_item, from, to);
ListView lst1 = (ListView) d.findViewById(android.R.id.list);
lst1.setAdapter(listAdapter);
lst1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
if (position == 0) {
// the code of color line
d.dismiss();
} else if (position == 1) {
// the code of blue line
d.dismiss();
} else {
// the code of yellow line
d.dismiss();
}
myView.postInvalidate();
}
});
d.show();
}
What is the code I have to add to make the color like what I selected ?
consider if I write this code
DrawerView.paint.setColor(Color.BLACK);
the whole line changes its color to the selected color and this is not what I want.
I want that the color of the new line is like what I selected and keep the old lines with its colors.
Hope anyone got my mean.
Thanks in advance.
Edit
the new code is:
ColoredPath.java
public class ColoredPath {
private Paint paint;
private Path path = new Path();
private int color;
public ColoredPath() {
paint = new Paint();
color = Color.BLACK;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
paint.setAntiAlias(true);
paint.setColor(color);
}
public ColoredPath(int color) {
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
paint.setAntiAlias(true);
paint.setColor(color);
}
public void setColor(int color){
this.color = color;
}
public int getColor(){
return color;
}
public void setPaint(Paint paint){
this.paint = paint;
}
public Paint getPaint() {
return paint;
}
public void setPath(Path path){
this.path = path;
}
public Path getPath() {
return path;
}
}
DrawerView.java
public class DrawerView extends View {
public Path circlePath = new Path();
public static int LINE_COLOR = 0;
public static boolean isTouchable = false;
public List<ColoredPath> paths = new ArrayList<ColoredPath>();
public ColoredPath currentPath;
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
currentPath = new ColoredPath();
paths.add(currentPath);
}
public void newLine(int color){
System.out.println("in newLine method");
currentPath = new ColoredPath(color);
paths.add(currentPath);
//postInvalidate();
}
public void onButtonPress(){
// resets the screen
currentPath.getPath().reset();
// Calls the onDraw() method
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
System.out.println("size of paths: "+paths.size());
canvas.drawPath(currentPath.getPath(), currentPath.getPaint());
for(int i = 0; i < paths.size(); ++i) {
//ColoredPath coloredPath = paths.get(i);
canvas.drawPath(currentPath.getPath(), currentPath.getPaint());
}
}
public Path getLastPath() {
Path path = new Path();
for(int i = 0; i < paths.size(); ++i) {
path.addPath(paths.get(i).getPath());
}
return path;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isTouchable){
return false;
} else {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
currentPath.getPath().moveTo(pointX, pointY);
//getLastPath().moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
currentPath.getPath().lineTo(pointX, pointY);
//getLastPath().lineTo(pointX, pointY);
circlePath.reset();
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
postInvalidate();
return true;
}
}
}
and in MainActivity.java
if (position == 1) {
// blue
myView.newLine(Color.BLUE);
d.dismiss();
}
this works well and colors the lines but when I select any color it leads to remove the last line and I want all lines with there colors.
Because Path itself doesn't contain any information about it's color (color is managed by Canvas) I would suggest you to create new pair of (Path, Paint) for every new path with different paint and use only current pair in onTouch event. So here is some code which illustrate this idea
public class ColoredPath {
private Paint paint;
private Path path;
public ColoredPath(Paint paint, Path path) {
this.paint = paint;
this.path = path;
}
public Paint getPaint() {
return paint;
}
public Path getPath() {
return path;
}
}
private List<ColoredPath> paths = new ArrayList<ColoredPath>();
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
//custom paint can be used here
paths.add(new ColoredPath(new Paint(), new Path()));
}
/////
#Override
protected void onDraw(Canvas canvas) {
for(ColoredPath coloredPath : paths) {
canvas.drawPath(coloredPath.getPath(), coloredPath.getPaint());
}
}
Where paths is List<ColoredPath>. And also you need field like ColoredPath currentPath.

Clear canvas in button click

I used following code to draw. I want to clear the previously drawn lines if the clear button is clicked.
public class MainActivity extends Activity {
private ArrayList<Path> _graphics = new ArrayList<Path>();
private Paint mPaint;
Activity activity;
View mView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity = this;
mView = new DrawingView(this);
activity.addContentView(mView, new LayoutParams(500,
LinearLayout.LayoutParams.WRAP_CONTENT));
init();
}
public void clear(View v) {
new DrawingView(activity).clearView();
}
private void init() {
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
class DrawingView extends View {
private Path path;
public DrawingView(Context context) {
super(context);
path = new Path();
this.setBackgroundColor(Color.BLACK);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
path.moveTo(event.getX(), event.getY());
path.lineTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
path.lineTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_UP) {
path.lineTo(event.getX(), event.getY());
_graphics.add(path);
}
invalidate();
return true;
}
#Override
public void onDraw(Canvas canvas) {
for (Path path : _graphics) {
canvas.drawPath(path, mPaint);
}
}
public void clearView() {
path = new Path();
invalidate();
}
}
}
Thank you.
import android.graphics.Color;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT);
for (Path path : _graphics) {
canvas.drawPath(path, mPaint);
}
}
or
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
canvas.drawPaint(mPaint);
mPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
for (Path path : _graphics) {
canvas.drawPath(path, mPaint);
}
}
See this Doc for more info.
Your clear method is wrong.
public void clear(View v) {
((DrawingView)mView).clearView();
}
Add the below in your Drawing view
Bitmap mBitmap;
Paint mPaint;
Canvas mCanvas;
int width,height;
public void clear()
{
_graphics.removeAll(_graphics);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
path = new Path();
invalidate();
}
Also add the below
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
In your onDraw add the below
canvas.drawBitmap(mBitmap, 0, 0, null);
To clear on button click
mView.clear();
This code works for me
clearbtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mBitmap.eraseColor(Color.TRANSPARENT);
mPath.reset();
mView.invalidate();
}
});
this method work for me,
public void Clear()
{
mBitmap.eraseColor(Color.TRANSPARENT);
mPath.reset();
invalidate();
}

How to move a circular image(png) using touch in android depending upon the touch

i want to rotate an image(png) in android depending upon the intensity of touch.
Any Idea?
public class GetmouseActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap mBitmap;
private ViewThread mThread;
private int mX;
private int mY;
public Panel(Context context) {
super(context);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
getHolder().addCallback(this);
mThread = new ViewThread(this);
}
public void doDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setStrokeWidth(25);
for (int y = 30, alpha = 255; alpha > 2; alpha >>= 1, y += 10) {
paint.setAlpha(alpha);
canvas.drawLine(0, y, 100, y, paint);
}
canvas.drawBitmap(mBitmap, mX, mY, null);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
if (!mThread.isAlive()) {
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mX = (int) event.getX() - mBitmap.getWidth() / 2;
mY = (int) event.getY() - mBitmap.getHeight() / 2;
return super.onTouchEvent(event);
}
}
public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
try this

Categories

Resources