This is my method for drawing on the touch screen.
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
float lastdownx = 0;
float lastdowny = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
path.addCircle(eventX, eventY, 50, Path.Direction.CW);
lastdownx = eventX;
lastdowny = eventY;
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
path.addCircle(lastdownx,lastdowny,0,Path.Direction.CW);
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
When i click on the screen down once it's drawing a circle.
I want to do when i remove my finger ACTION_UP it will delete the drawn circle.
The way i'm doing it now does nothing to the drawn circle.
You can make two different paths.
One for the line you are drawing.
Second one for the circle which you want to follow your finger.
This way you can only reset the path that is keeping your circle data, and leave the line path.
Here is a code example:
private Path pathSave = new Path(); //The path for the circle you wish to save.
You can use the same paint for the circle if you wish, but I tweaked my example a bit and I added a different paint and size for the circle.
private Paint paintCircle = new Paint();
paintCircle.setAntiAlias(true);
paintCircle.setStrokeWidth(20);
paintCircle.setColor(Color.LTGRAY);
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setStrokeJoin(Paint.Join.ROUND);
In the onDraw method you want to draw both paths like so:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
canvas.drawPath(pathSave ,paintCircle);
}
For the logic:
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY); //Only paint the line path.
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
pathSave.reset(); //Reset the circle.
pathSave.addCircle(eventX,eventY,50,Path.Direction.CW); //Draw circle
break;
case MotionEvent.ACTION_UP:
pathSave.reset(); //On lifting finger circle dissapears.
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
Hope this fits what you are looking for.
Related
Refer to the video below, here's my current code :
Inside of Oncreate method :
rootLayout = findViewById(R.id.relativemain);
And this method is where I put the Gif images to act as the chips, I also need help into this one because when I add the addRule to change the location of the chip, It turns out that I can no longer drag it:
private void mvb_chip(ImageView view, int a) {
view = rootLayout.findViewById(a);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(300, 300);
view.setLayoutParams(layoutParams);
view.setVisibility(View.VISIBLE);
view.setOnTouchListener(new mvb_direct.ChoiceTouchListener());
}
And Lastly here Is the touch listener to drag the chips! Inside of the ACTION.UP is where I drag the chips and put a drawline (credits to this guys answer https://stackoverflow.com/a/28489989/19026761, and my problem is why the drawLine is not exactly similar to my touch X and Y, see the video below.
float startX;
float startY;
private final class ChoiceTouchListener implements View.OnTouchListener {
#Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
Paint paint = new Paint();
paint.setColor(Color.CYAN);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
drawbleView.getCanvas().drawLine(startX,startY,event.getRawX(),event.getRawY(),paint);
drawbleView.invalidate();
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250
I want to connect two opposite radiobuttons or normal Buttons with a line in Canvas like this: image
I have the FingerLine Class to draw the red line and in the layout I have 3 columns (RecyclerView,FingerLine,RecyclerView). I want to develop an application to match two image with lines.
Currently what I do is draw in the middle but I would like the drawing line to go from one button to another I don't know how to do it.
public class FingerLine extends View {
private final Paint mPaint;
private float startX;
private float startY;
private float endX;
private float endY;
float joinX, joinY = 0;
ArrayList<Line> lines = new ArrayList<Line>();
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);
}
}
public FingerLine(Context context) {
this(context, null);
}
public FingerLine(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.RED);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, mPaint);
}
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (joinX <= 0 || joinY <= 0) {
lines.add(new Line(event.getX(), event.getY()));
}else{
lines.add(new Line(event.getX(), event.getY()));
}
break;
case MotionEvent.ACTION_MOVE:
if(lines.size() > 0) {
Line current = lines.get(lines.size() - 1);
current.stopX = event.getX();
current.stopY = event.getY();
invalidate();
break;
}
case (MotionEvent.ACTION_CANCEL):
break;
case (MotionEvent.ACTION_OUTSIDE):
break;
case MotionEvent.ACTION_UP:
if(lines.size() > 0) {
Line current = lines.get(lines.size() - 1);
current.stopX = event.getX();
current.stopY = event.getY();
joinX = event.getX();
joinY = event.getY();
invalidate();
break;
}
}
return true;
}
}
I think for first you have to find an image of a line.
then you have to create 6(or how many you want) imageview s with the image of line and then make them invisible with android:visibility = "invisible".
then you have to find two checked radiobuttons in your activity.java and then set align_right and align_left to the checked radiobuttons for your imageview in activity.java and then make it visible.
I am trying to draw to different circles when the user touches the screen and when the touch is removed.
I am somewhat successfull but the start touch circle disapperas when the "ACTION_UP" event circle is drawn.
Not sure What is going wrong.
My OnDraw and OnTouch functions are below
public void onDraw(Canvas canvas) {
//drawing lines
//lines
canvas.drawCircle(point.x, point.y, 5, paint);
//circles
//canvas.drawCircle(point.x, point.y, 5, paint);
}
public boolean onTouch(View view, MotionEvent event) {
// if(event.getAction() != MotionEvent.ACTION_DOWN)
// return super.onTouchEvent(event);
// points.add(point);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN :
point.x = (int)event.getX();
point.y = (int)event.getY();
paint.setColor(Color.BLACK);
break;
case MotionEvent.ACTION_UP:
point.x = (int)event.getX();
point.y = (int)event.getY();
paint.setColor(Color.BLUE);
break;
}
invalidate();
return true;
}
}
if you are trying to draw multiple circles when the user touches the screen and touch removed, you need to use a List of circles. you can have an ExampleCircle class where it have an x,y and color field.
public class ExampleCircle{
int x,y;
Color color;
//setters and getters
}
//onTouch
//assuming you already have a List object (List circleList=new ArrayList(); )
ExampleCircle newCircle=new ExampleCircle();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN :
newCircle.setX((int)event.getX());
newCircle.setY((int)event.getY()) ;
newCircle.setColor(paint.setColor(Color.BLACK));
break;
case MotionEvent.ACTION_UP:
newCircle.setX((int)event.getX());
newCircle.setY((int)event.getY()) ;
newCircle.setColor(paint.setColor(Color.BLACK));
break;
}
circleList.add(newCircle);
invalidate();
return true;
//on draw method
replace
canvas.drawCircle(point.x, point.y, 5, paint);
with
for(int i=0;i<circleList.size();i++){
ExampleCircle currentCircle=circleList.get(i);
canvas.drawCircle(currentCircle.getX(), currentCircle.getY(), 5, paint or currentCircle.getColor());
}
I'd like to draw a series of images from touch event triggered. From the returned path inside onDraw, I will use it as a guide on where to draw the images. My problem right now is to have a series of random images displayed, not just one. Then eventually the images displayed will slowly fade out.
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
float eventX;
float eventY;
Bitmap bmp;
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
/*Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_stub);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp, 10, 10, null);*/
canvas.drawPath(path, paint);
int rand = (int) (Math.random() * 3);
Log.d("Integer", ""+rand);
if(rand==0){
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_stub);
}else
if(rand==1)
{
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_stub);
}
else if(rand==2)
{
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.bg_striped_img);
}
canvas.drawBitmap(bmp, eventX, eventY, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
eventX = event.getX();
eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
}
You'll see in the picture that, on the left is a normal line and on right is a dashed line. After I selected the dashed line, the normal line was transformed into a dashed line. If I try to paint with a normal line, it will transform the dashed line in normal line.
Here is the View I used to create each line:
public void setDashLine(){
dashedLine = true;
paint = new Paint();
paint.setPathEffect(dashEffect);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
public void setNormalLine(){
//paint.setColor(Color.BLACK);
dashedLine = false;
paint.setPathEffect(null);
paint.setStyle(Paint.Style.STROKE);
paint.setPathEffect(null);
paint.setAntiAlias(true);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
protected void onDraw(Canvas canvas) {
if(dashedLine){
paint.setPathEffect(dashEffect);
}
else {
paint.setPathEffect(null);
}
final OnTouchListener drawLineListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
FirstActivity.ll.setVisibility(LinearLayout.GONE);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
myLine = new MyLine();
myLine.xStart = event.getX();
myLine.yStart = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
myLine.xEnd = event.getX();
myLine.yEnd = event.getY();
invalidate();
lineList.add(myLine);
break;
default:
Log.d("mock it up", "Unknown touch event " + event.toString());
return false;
}
return true;
}
};
final OnTouchListener drawDashedLineListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
FirstActivity.ll.setVisibility(LinearLayout.GONE);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
break;
default:
Log.d("mock it up", "Unknown touch event " + event.toString());
return false;
}
return true;
}
};
Should you call:
paint = new Paint();
in
public void setNormalLine()?