I am trying to implement a Drawing Application in Android. Where the user should be able to select and move the drawn shapes.
Currently i have statically drawn some rects and text on my Drawing Canvas:
View mDrawingCanvas = new View(mContext)
{
ShapeDrawable rectangle;
#Override
public boolean isFocused() {
// TODO Auto-generated method stub
Log.d(TAG, "View's On focused is called !");
return super.isFocused();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return super.onTouchEvent(event);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
// Work out current total scale factor
// from source to view
final float scale = mSourceScale*(float)getWidth()/(float)mSize.x;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
//Custom View
rectangle = new ShapeDrawable(new RectShape());
rectangle.getPaint().setColor(Color.GRAY);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
rectangle.setBounds((int)(50*scale), (int)(30*scale), (int)(200*scale), (int)(150*scale));
rectangle.draw(canvas);
rectangle.getPaint().setColor(Color.BLUE);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
rectangle.setBounds((int)(200*scale), (int)(200*scale), (int)(400*scale), (int)(350*scale));
rectangle.draw(canvas);
}
};
I want to select (draw borders on the selected shape) and move the drawn Shapes in onTouch events of the drawing canvas.
Can some one please guide me about this, any help is Highly Appreciated.
This answer has demonstrated the Shape Moving Methodology that i was looking for.
And my problem is solved now. The Link is :
Drag and move a circle drawn on canvas
You should save the X and Y positions in the touch event and use them when drawing your shapes.
Below is a very basic example of how to do this, but you need to improve it (check if the touch is inside the object and only change values for that object)
Example:
public class DrawTest extends View {
private static final String TAG = "Desenho";
private ShapeDrawable rectangle;
private Paint paint;
private float currX, currY;
private Rect blue, gray;
public DrawTest(Context context) {
super(context);
currX = 1;
currY = 1;
gray = new Rect(50,30,200,150);
blue = new Rect(200,200,400,350);
paint = new Paint();
rectangle = new ShapeDrawable(new RectShape());
}
#Override
public boolean isFocused() {
Log.d(TAG, "View's On focused is called !");
return super.isFocused();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
currX = event.getX();
currY = event.getY();
invalidate();
Log.d(TAG, "View's On touch is called! X= "+currX + ", Y= "+currY);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
//Custom View
rectangle.getPaint().setColor(Color.GRAY);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
gray.set((int)(50+currX), (int)(30+currY), (int)(200+currX), (int)(150+currY));
rectangle.setBounds(gray);
gray = rectangle.getBounds();
rectangle.draw(canvas);
rectangle.getPaint().setColor(Color.BLUE);
rectangle.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
rectangle.getPaint().setStrokeWidth(3);
blue.set((int)(200+currX), (int)(200+currY), (int)(400+currX), (int)(350+currY));
rectangle.setBounds(blue);
blue = rectangle.getBounds();
rectangle.draw(canvas);
}
}
Related
I am unable to get the canvas object in ontouch().Without the canvas I cannot draw a circle when touched.How can I draw any shape or image when touched
public class Board extends View implements View.OnTouchListener {
public Board(Context context) {
super(context);
Paint paint1 = new Paint();
paint1.setTextSize(50);
paint1.setColor(Color.WHITE);
View view=this;
view.setOnTouchListener(this);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(200, 100, 0);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
final int action = MotionEventCompat.getActionMasked(event);
int pointer = MotionEventCompat.getActionIndex(event);
if (action == MotionEvent.ACTION_DOWN) {
canvas.drawCircle(70, 1100, 50, paint1);
}
return false;
}
To draw on canvas wherever you touch, you need a path to keep track of your touch points and path. Using the path object you can draw on canvas. See this answer Draw on touch
I am creating an app to draw free shapes on the surface screen but i could only draw separated points my problem is . i want the points to be connected to each other when i draw them not lifting my finger from the screen . i mean as long as i am touching the screen draw.here's my code so far.
public class SurfaceViewActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawingView(this));
}
class DrawingView extends SurfaceView {
private final SurfaceHolder surfaceHolder;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private List<Point> pointsList = new ArrayList<Point>();
public DrawingView(Context context) {
super(context);
surfaceHolder = getHolder();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (surfaceHolder.getSurface().isValid()) {
// Add current touch position to the list of points
pointsList.add(new Point((int)event.getX(), (int)event.getY()));
// Get canvas from surface
Canvas canvas = surfaceHolder.lockCanvas();
// Clear screen
canvas.drawColor(Color.BLACK);
// Iterate on the list
for(int i=0; i<pointsList.size(); i++) {
Point current = pointsList.get(i);
// Draw points
canvas.drawPoint(current.x, current.y, paint);
}
// Release canvas
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
}
you can use this function to draw smooth lines
public void drawBrzierLine(Canvas mCanvas, float xi, float yi, float xd, float yd) {
Point start = new Point((int) xi, (int) yi);
Point end = new Point((int) xd, (int) yd);
Path mPath = new Path();
mPath.reset();
mPath.moveTo(start.x, start.y);
mPath.quadTo(start.x, start.y, end.x, end.y);
mCanvas.drawPath(mPath, mPaint);
}
In onTouchEvent(MotionEvent event) you only handle ACTION_DOWN. So this code will only run when you press down on the screen. Use ACTION_MOVE instead.
http://developer.android.com/reference/android/view/MotionEvent.html
I want to place red circles where I touch an image and have a class that listens to the touch and sends the coordinates to an other class:
public class Report extends Fragment {
private Context activity;
private Point point = new Point();
private DrawingCrl imgCircle = new DrawingCrl();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.report, container,
false);
activity = this.getActivity();
//Where I'm doing the touching and respond to that:
final View touchView = rootView.findViewById(R.id.ImageC);
touchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
point.x = Float.valueOf(event.getX());
point.y = Float.valueOf(event.getY());
touchView = imgCircle.DrawCircle(Point point);
return true;
}
});
return rootView;
public class Point {
float x;
float y;
}
}
When I call the DrawCircle I want the class DrawingCrl to do just that, draw a circle for me on the point I send to the method:
public class DrawingCrl {
private Bitmap mBitmap;
private Paint paint;
private Canvas canvas = new Canvas();
public void DrawCircle(Point point) {
mBitmap = Bitmap.createBitmap(400, 800, Bitmap.Config.ARGB_8888);
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
canvas.drawCircle(point.x, point.y, 50, paint);
}
}
I have read both getting X and Y coordinates and drawing circle and Draw Circle on touch but don't get how to do the drawing of the circle.
I'm pretty new to android so sorry my many noob failures. I hope you can help me get this working! Thanks! :)
Okay, here's how I would do it but I'm going to change your code a bit.
First I would change your DrawingCrl class to just store location (and possibly Paint object but this would probably fit better as a static shared by all DrawingCrls) like this:
public class DrawingCrl {
public Point myLoc;
public Paint paint;
public void DrawCircle(Point point) {
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
myLoc = point;
}
}
Save a Vector of DrawingCrl objects created in your Activity and create new ones in the onTouch event handler.
This goes in the Report class:
java.util.Vector<DrawingCrl> myCircles = new java.util.Vector<DrawingCrl>();
Then in 'onTouch' create a new circle object and save it:
#Override
public boolean onTouch(View v, MotionEvent event) {
point.x = Float.valueOf(event.getX());
point.y = Float.valueOf(event.getY());
// create a new Circle here and save it
DrawingCrl c = new DrawingCrl(point);
myCircles.add(c);
return true;
}
Then I would override the 'onDraw' method of your View 'touchView'.
The 'onDraw' will give you the Canvas to draw to, so don't create your own like you are doing in your DrawingDMG class right now.
#Override
protected void onDraw(Canvas c)
{
for (DrawingCrl c : myCircles)
{
c.drawCircle(c.myLoc.x, c.myLoc.y, 50, c.paint);
}
}
I am having doubt related to working of canvas while drawing , it is mentioned that canvas holds the drawing calls and bitmap holds the actual pixel data ,for e.g in the code
public class MyView extends View{
private Paint _p;
public float x=10,y=10;
private Canvas _canvas;
static int cnt=0;
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
_p = new Paint();
_p.setColor(Color.GREEN);
_canvas = new Canvas();
this.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
cnt++;
_canvas.drawCircle(event.getX(), event.getY(), 10, _p);
if(cnt>3){
cnt = 0;
invalidate();
}
return false;
}
});
}
public void onDraw(Canvas can){
_canvas = can;
super.onDraw(_canvas);
_canvas.drawColor(Color.BLACK);
_canvas.drawCircle(x, y, 10, _p);
x = x +10;
y= y+10;
}
}
3 circles should be drawn but it is not the case , can anybody please explain me?thanks in advance
Regards,
Rohit
Your onTouch only has a one time check to draw the circle, it's not a recursive loop to keep drawing until 3 are drawn. This is assuming your _canvase.drawCircle() event (which isn't shown) doesn't draw 3 circles.
I am creating a custom control as below in the image. It is a semicircle with places 1, 2 etc.
When user click on one place (1, 2 etc), it changes color (for example user click on place 3, image 2).
I try to use canvas and methods draws. But I don't think that is correct. Can you help me with a better solution and how to set up an event for user clicking on the place?
You can do it with the canvas, bellow is a small example of a View with 2 oval shapes that change color(to red) on a touch event:
class ExtraView extends View {
private boolean flag1, flag2;
private Paint p1, p2;
private RectF oval1, oval2;
public ExtraView(Context context) {
super(context);
flag1 = false;
flag2 = false;
// bigger oval paint
oval1 = new RectF(50, 50, 460, 360);
p1 = new Paint();
p1.setStrokeWidth(2.0f);
// smaller oval paint
oval2 = new RectF(140, 140, 360, 260);
p2 = new Paint();
p2.setStrokeWidth(2.0f);
}
#Override
public void draw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
// bigger oval
if (flag1) {
p1.setColor(Color.RED);
} else {
p1.setColor(Color.WHITE);
}
p1.setStyle(Paint.Style.FILL);
canvas.drawOval(oval1, p1);
p1.setColor(Color.BLACK);
p1.setStyle(Paint.Style.STROKE);
canvas.drawOval(oval1, p1);
// smaller oval
if (flag2) {
p2.setColor(Color.RED);
} else {
p2.setColor(Color.WHITE);
}
p2.setStyle(Paint.Style.FILL);
canvas.drawOval(oval2, p2);
p2.setColor(Color.BLACK);
p2.setStyle(Paint.Style.STROKE);
canvas.drawOval(oval2, p2);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (oval2.contains(event.getX(), event.getY())) {
flag2 = !flag2;
invalidate();
} else if (oval1.contains(event.getX(), event.getY())) {
flag1 = !flag1;
invalidate();
}
}
return true;
}
}