I'd Like to know how to draw a Line on ImageView as user swipe their finger ?
Could any body explain this ? Or perhaps any Link to get start on this.
You must have your own ImageView and override onDraw function. Use something like this
public class MyImageView extends ImageView{
public MyImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawLine(0, 0, 20, 20, p);
}
}
and in your main class create object MyImageView; and when you touch your display call the update(); function
This is a complete example of how you can draw green rectangle over another image:
package CustomWidgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
/**
* Allows to draw rectangle on ImageView.
*
* #author Maciej Nux Jaros
*/
public class DrawImageView extends ImageView {
private Paint currentPaint;
public boolean drawRect = false;
public float left;
public float top;
public float right;
public float bottom;
public DrawImageView(Context context, AttributeSet attrs) {
super(context, attrs);
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00CC00); // alpha.r.g.b
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (drawRect)
{
canvas.drawRect(left, top, right, bottom, currentPaint);
}
}
}
When you have this defined you can replace ImageView with above View (widget) for example:
<CustomWidgets.DrawImageView
android:id="#+id/widgetMap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/map_small"
/>
Then you can use this for example in touch event of the activity that controls the layout:
mapImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
DrawImageView drawView = (DrawImageView) v;
// set start coords
if (event.getAction() == MotionEvent.ACTION_DOWN) {
drawView.left = event.getX();
drawView.top = event.getY();
// set end coords
} else {
drawView.right = event.getX();
drawView.bottom = event.getY();
}
// draw
drawView.invalidate();
drawView.drawRect = true;
return true;
}
});
Of course you could make some getters and setters and other Java over-engineering routines ;-).
For drawing the line the user actually drew you have to override the dispatchTouchEvent. From that event you can get the coordinates of the line and draw them in the onDraw as shown by george.
http://developer.android.com/reference/android/app/Activity.html#dispatchTouchEvent(android.view.MotionEvent)
Take a look at the ApiDemos sample FingerPaint.
By using this you can draw line on ImageView by touching on the screen.
Related
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);
}
}
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.
Currently on a view I have a ImageView and A custom class that draws a circle on the view. It will draw the circle on the view but it is hidden behind the image view. I know its there because when the radius is big enough I can see a small section that isn't behind the imageview. What code would bring it to the front?
EDIT: Found out that the above issue is not the problem. It seems that it is only drawing it on the portion that is reserved for the seekbar I have on the view?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_process);
mDraw = new Draw(this);
addContentView(mDraw, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
seekBar1 = (SeekBar) findViewById(R.id.seekBar1);
b = (Button) findViewById(R.id.button1);
seekBar1.setMax(500);
seekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
public void onStartTrackingTouch(SeekBar seekBar) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
public void onStopTrackingTouch(SeekBar seekBar) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
});
}
Here is the Draw class:
package org.DTS.boltsize;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
public class Draw extends View {
private int x = 1;
private int y = 1;
private int r = 1;
public Draw(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void setCords(int mx, int my, int mr ){
x = mx;
y = my;
r = mr;
}
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
System.out.println("Drew :)");
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawCircle(x, y, r, paint);
super.onDraw(canvas);
}
public void DrawCirlce(Canvas canvas, int x, int y, int r){
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
canvas.drawCircle(x, y, r, paint);
super.onDraw(canvas);
}
}
Here is what it looks like. That red circle should cover the entire screen.
I would draw to a seperate bitmap that you have in a different imageView in the same space as your curent bitmap possibly in a FrameLayout. You can then use .bringToFront to decide the z order.
Solved by converting source to bitmap, then drawing a circle on that bitmap and sending that final bitmap to the imageview.
I have DrawView. If I touch this view it draws small circles. I wont to draw circles but not to touch view - with help function "setPoints". What I do:
package com.samples;
import ...
public class DrawView extends View {
ArrayList<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
private int pSize = 5;
private int pColor = Color.BLACK;
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.setOnTouchListener(this);
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
}
return true;
}
});
requestFocus();
}
#Override
public void onDraw(Canvas canvas) {
for (Point point : points) {
canvas.drawCircle(point.x, point.y, pSize, paint);
}
}
public void setPoints(Float xP, Float yP)
{
Point point = new Point();
point.x = xP;
point.y = yP;
points.add(point);
postInvalidate();
}
}
class Point {
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
Please tell me, how get canvas out setPoints function?
Update:
Wow, it's really interesting problem. My DrawView contains in HorizontalScrollView. Because if I set in this DrawView right coordinates, no one knows where are drawable circles.
You can't. The canvas is managed by the system and is passed to your onDraw(). I don't understand why you'd need it outside of there. Just redeclare setPoints like this
public void setPoints(Canvas canvas, Float xP, Float Yp)
You can keep a cache of the previous drawings (or store the previous points)
Try declaring canvas2 as a public variable in the DrawView class.
You draw your circles in onDraw(). That's the way View is supposed to work (technically it's actually in the draw() method but we'll overlook that). In setPoints(), set the points of the circle in variables within the class scope, call invalidate(), then draw the circle like that in onDraw(). If you follow this method, you're following the class flow that the view was designed for.
package com.ewebapps;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class Dot extends View {
private final float x;
private final float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mWhite = new Paint(Paint.ANTI_ALIAS_FLAG);
public Dot(Context context, float x, float y, int r) {
super(context);
mPaint.setColor(0xFF000000); //Black
mWhite.setColor(0xFFFFFFFF); //White
this.x = x;
this.y = y;
this.r = r;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r+2, mWhite); //White stroke.
canvas.drawCircle(x, y, r, mPaint); //Black circle.
}
}
Well... when creating your own views, the best way to accomplish that is overriding the dispatchTouchEvent method. Trust me, using setOnTouchListener and onTouchEvent don't work well in some scenarios. This is all you have to do in your View:
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
// put your logic here
return super.dispatchTouchEvent(event);
}
documentation with example
View aView = (View)findViewById(R.id.DotView);
aView.setOnTouchListener(this);
Full Example Here
Aaron Saunders answer works for views(like buttons) because an onTouchListener only tells you what view was clicked and not exactly where. If you need to know exactly where the event was without creating buttons try this in your activity class:
#Override
onTouchEvent(MotionEvent event) {
int _x = event.getX();
int _y = event.getY();
// do stuff
}
Note: onTouchEvent is only called when the event is NOT handled by a view.
Documentation
(Can someone tell me how to add line breaks?)