Draw a semi oval like shape in android - java

Im trying to draw an arc in android, between two textView using drawArc. My requirement is to achieve an arc as shown in the image which is correct arc shape.
But when i tried ,i'm not getting an perfect arc shape and i got the arc which is of semi ovalshaped.
Here is my code snippet:
public class ArcView extends View {
final RectF oval = new RectF();
Path myPath = new Path();
Paint paint;
float left, top, right, bottom;
public FlightStatusArcView(Context context) {
super(context);
}
public FlightStatusArcView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public FlightStatusArcView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet set) {
if (set == null)
return;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public void setArcProperties(float l, float t, float r, float b) {
left = l;
top = t;
right = r;
bottom = b;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
oval.set(left, top, right, bottom);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
canvas.drawArc(oval, 180f, 180f, false, paint);
drawArrow(canvas);
}
private void drawArrow(Canvas canvas) {
canvas.save();
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.FILL);
p.setStrokeWidth(4f);
float startX = oval.left + 20;
float startY = oval.top + (oval.centerY() - oval.top)/ 2;
Path path = new Path();
path.moveTo(startX, startY-20);
path.lineTo(startX + 20, startY + 20);
path.lineTo(startX + 30, startY -17);
path.close();
canvas.drawPath(path, p);
canvas.restore();
}
}
Please help how to achieve the perfect arc shape using the canvas apis.

You could use a Path together with quadTo or cubicTo to draw a curve like this. This will allow you to draw quadratic or cubic bezier curves. For instance, a cubic bezier curve with two identical control points (x2, y2) is constructed like this:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
Path p = new Path();
float x1 = 100;
float y1 = 256;
float x2 = 400;
float y2 = 32;
float x3 = 700;
float y3 = 256;
p.moveTo(x1, y1);
p.cubicTo(x2, y2, x2, y2, x3, y3);
canvas.drawPath(p, paint);
drawArrow(canvas);
}
This is the result:
You can find more information on cubicTo and quadTo in the official documentation

Related

How to draw a navigation path using Canvas onDraw() in android java

I am new to java drawing and I would like to implement a navigation system so a user can navigate on a map. The java function 'onDraw' is implement so it shows the location of the user on the map and also show his movements. Below are my codes:
class CanvasView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private float lineX = Position.x_axis;
private float lineY = Position.y_axis;
private float lastX = Position.x_axis;
private float lastY = Position.y_axis;
public CanvasView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setStrokeWidth(10f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
drawRotateImage(canvas);
canvas.drawPoint(Position.x_axis, Position.y_axis, paint);
Path path = new Path();
path.moveTo(lastX, lastY);
path.lineTo(lineX,lineY);
canvas.drawPath(path, paint);
}
private void stepDetector (float step) {
stepCount += (int) step;
distance = stepCount * 30;
lineX = (float) (lineX + 30);
lineY = (float) (lineY + 30);
invalidate();
lastX = lineX;
lastY = lineY;
}
}
The stepdetector is called each time a step has been detected and it should repaint the canvas to show to movements. Noting that the previous movement line needs to be visible, that is it should be a continuous line.
I am having issues to get the navigation line path. It would be grateful if I can get some help on it.
Thank you in advance.
try this, make list and for every step add points, and in ondraw draw all points from list
class CanvasView extends View {
List<Point> points;
private Paint paint = new Paint();
private Path path = new Path();
private float lineX = Position.x_axis;
private float lineY = Position.y_axis;
private float lastX = Position.x_axis;
private float lastY = Position.y_axis;
public CanvasView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setStrokeWidth(10f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
points=new ArrayList<>();
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
drawRotateImage(canvas);
canvas.drawPoint(Position.x_axis, Position.y_axis, paint);
// now here draw all points from list
Path path = new Path();
path.moveTo(lastX, lastY);
path.lineTo(lineX,lineY);
canvas.drawPath(path, paint);
}
private void stepDetector (float step) {
stepCount += (int) step;
distance = stepCount * 30;
lineX = (float) (lineX + 30);
lineY = (float) (lineY + 30);
invalidate();
lastX = lineX;
lastY = lineY;
// add every point to the list after step
}
class Point{
float x,y;
}
}
The onDraw draws a fresh copy of the contents everytime and does not remain old information. For what you are trying to draw, you can keep a list of type Position and add the new position to the list when stepDetector is called.
Then, inside onDraw, iterate over the list and draw lines connecting all the points from the list .

Canvas not drawing on finger location when zoomed

I am trying to make a painting app. Zoom kinda works, when i try to draw on canvas after the zoom, it does not draw on the location of the finger. instead it draws scale to the device screen.
I did some research but could not find the answer to the solution.
-> float x = (event.getX() - scalePointX)/mScaleFactor; // does not work,
I tried to implement matrix but was unsuccessful.
Can someone please help me to draw on the finger when the canvas is zoomed in or out?
Thank you!
public class paintView extends View {
Paint paint;
Path path;
Bitmap bitmap;
Canvas mcanvas;
private final float TOUCH_TOLERANCE = 4;
private float mX, mY;
public static final int DEFAULT_BG_COLOR = Color.WHITE;
private int backgroundColor = DEFAULT_BG_COLOR;
private ArrayList<FingerPath> paths = new ArrayList<>();
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
private final ScaleGestureDetector mScaleGesture;
private float mScaleFactor = 1.f;
private float mPosX;
private float mPosY;
private float scalePointX, scalePointY;
private Rect clipBounds_canvas;
public paintView(Context context) {
this(context, null);
}
public paintView(Context context, AttributeSet attrs){
super(context, attrs);
mScaleGesture = new ScaleGestureDetector(context, new ScaleListener());
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8f);
}
public void init(DisplayMetrics metrics){
int height = metrics.heightPixels;
int width = metrics.widthPixels;
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mcanvas = new Canvas(bitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mcanvas.drawColor(backgroundColor);
clipBounds_canvas = canvas.getClipBounds();
for(FingerPath fp: paths){
paint.setMaskFilter(null);
mcanvas.drawPath(fp.path, paint);
}
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor,scalePointX,scalePointY);
canvas.drawBitmap(bitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y){
path = new Path();
FingerPath fp = new FingerPath(path);
paths.add(fp);
path.reset();
path.moveTo(x,y);
mX = x;
mY = y;
}
private void touchMove(float x, float y){
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if(dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE ){
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX = x;
mY = y;
}
}
private void touchUp(){
path.lineTo(mX,mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final float x = (event.getX() - scalePointX)/mScaleFactor;
final float y = (event.getY() - scalePointY)/mScaleFactor;
mScaleGesture.onTouchEvent(event);
final int action = event.getAction();
switch(action & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
invalidate();
break;
}
return true;
}
public class FingerPath {
public Path path;
public FingerPath(Path path) {
this.path = path;
}
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
scalePointX = detector.getFocusX();
scalePointY = detector.getFocusY();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 3.0f));
//zoom out 'up to' the size of canvas(screen size)
//mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
invalidate();
return true;
}
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
}
}
I had that problem and was able to solve it with This stack overflow question. What I did was store the current scale offset and when I draw the new paths, I'd offset the drawing matrix by this stored value. Your solution is really close, instead of scaling the canvas you can scale the drawing matrix. Also a friendly tip, you might need to scale the line thickness after zooming also, so use the same value that was stored to scale.

Denote progress by border Android

I need to denote progress by the border of view.
E.g. Initially view will not have any border at all, when 50% progress is reached, only 50% of view will get border.Find the attached image.
I did lot of googling but no luck.The view I used is textview.
Edited
The following code, cuts the edges of bitmap.
What I've done in this code is -
1. Bg is set to Black Hexagon
2. And I've taken hollow green bordered hexagon & revealing this hollow hexagon, so that it will look like border is getting accumulated.
public class MyView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private RectF mOval;
private float mAngle = 135;
private Paint mTextPaint;
private Bitmap bgBitmap;
public MyView(Context context) {
super(context);
doInit();
}
/**
* #param context
* #param attrs
* #param defStyleAttr
*/
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
doInit();
}
/**
* #param context
* #param attrs
*/
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
doInit();
}
private void doInit() {
// use your bitmap insted of R.drawable.ic_launcher
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hexagon_border);
bgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.view_message_small_hexagon);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(48);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setColor(0xffffaa00);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Matrix m = new Matrix();
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
m.setRectToRect(src, dst, ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
shader.setLocalMatrix(m);
mPaint.setShader(shader);
m.mapRect(mOval, src);
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xff0000aa);
Matrix matrix = new Matrix();
canvas.drawBitmap(bgBitmap, matrix, null);
canvas.drawArc(mOval, -90, mAngle, true, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mAngle = (float) Math.toDegrees(Math.atan2(event.getY() - h2, event.getX() - w2));
mAngle += 90 + 360;
mAngle %= 360;
invalidate();
return true;
}
}
try this SO answer:
public class MyView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private RectF mOval;
private float mAngle = 135;
private Paint mTextPaint;
public MyView(Context context) {
super(context);
// use your bitmap insted of R.drawable.ic_launcher
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mOval = new RectF();
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(48);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setColor(0xffffaa00);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Matrix m = new Matrix();
RectF src = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
RectF dst = new RectF(0, 0, w, h);
m.setRectToRect(src, dst, ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
shader.setLocalMatrix(m);
mPaint.setShader(shader);
m.mapRect(mOval, src);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xff0000aa);
canvas.drawArc(mOval, -90, mAngle, true, mPaint);
canvas.drawText("click me", getWidth() / 2, getHeight() / 2, mTextPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mAngle = (float) Math.toDegrees(Math.atan2(event.getY() - h2, event.getX() - w2));
mAngle += 90 + 360;
mAngle %= 360;
invalidate();
return true;
}
}
Getting a good circular progress spinner is difficult in itself. The ProgressWheel is a good custom View that does this. You should be able to modify the ProgressWheel's onDraw() class to do something very similar to what you want.

Android Paint: how to get "airbrush" effect?

I am following the "FingerPaint" demo in the API Demos.
I would need to get an "airbrush" effect, in the sense that when I draw over the same spot it gets darker and darker.
Please see the image:
as you can see the center is darker because I passed with the paint on the same spot more than one time.
Please how do I get the same effect, of getting darker a spot if drawn over more than one time?
EDIT EDIT EDIT
the suggested
mPaint.setAlpha(0x80)
kind of work, but only if I release touch and then touch again, if I do not release and keep the finger on the screen the effect is not reached.
The point is that you do not reach the effect if you do not release your finger from the screen, if you keep on drawing without releasing the touch it doesn't get darker when paint over. If you release the touch and then draw again you get the effect
This is the result I get. And I do not want:
this would be the desired result:
this is is the code taken form the API Demos:
public class FingerPaint extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0x44FF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}
private Paint mPaint;
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public MyView(Context c) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
}
I made only few minor changes in your code.
mPaint.setColor(Color.BLACK);// changed color to balck
mPaint.setAlpha(0x80); // only change
Activity class
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setAlpha(0x80); // only change
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}
private Paint mPaint;
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public MyView(Context c) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
}
snap shot
This approach is more of a simulation the way something like Photoshop would do it: Integrate along the path and draw individual paint splashes with an adjustable spacing inbetween.
public class DrawView extends View {
public Paint mPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private int strokeRadius;
private ShapeDrawable mBrush;
private Paint mBitmapPaint;
private float mPreviousX, mPreviousY;
public DrawView(Context context, AttributeSet attrs) {
super( context, attrs);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
int strokeWidth = 20;
strokeRadius = strokeWidth/2;
Shape brushShape = new OvalShape();
mBrush = new ShapeDrawable(brushShape);
Paint paint = mBrush.getPaint();
// radial gradient shader with a transparency falloff, if you don't want this,
// just set a color on the paint and remove the setShader call
Shader shader = new RadialGradient(strokeRadius, strokeRadius, strokeRadius,
Color.argb(255, 0, 0, 0), Color.argb(0, 0, 0, 0), Shader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAlpha(0x10);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFF00B8F5);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}
private void touch_start(float x, float y) {
mPreviousX = x;
mPreviousY = y;
}
private void touch_move(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
// get vector from previous to current position
float xdist = x - mPreviousX;
float ydist = y - mPreviousY;
// get the length
float segmentLength = (float) Math.sqrt(xdist * xdist + ydist * ydist);
// derive a suitable step size from stroke width
float stepSize = Math.max(strokeRadius / 10, 1f);
// calculate the number of steps we need to take
// NOTE: this draws a bunch of evenly spaced splashes from the start point
// to JUST BEFORE the end point. The end point will be drawn by the start point of the
// next stroke, or by the touch_up method. If we drew both the start and
// end point there it would be doubled up
int steps = Math.max(Math.round(segmentLength / stepSize), 2);
for(int i = 0; i < steps; ++i)
{
int currentX = (int) (mPreviousX + xdist * i / steps);
int currentY = (int) (mPreviousY + ydist * i / steps);
drawSplash(currentX, currentY);
}
// update the previous position
mPreviousX = x;
mPreviousY = y;
}
private void touch_up(MotionEvent event) {
drawSplash((int) event.getX(), (int)event.getY());
}
/**
* draws the brush to the canvas, centered around x and y
* #param x
* #param y
*/
private void drawSplash(int x, int y)
{
mBrush.setBounds(x - strokeRadius, y - strokeRadius, x + strokeRadius, y + strokeRadius);
mBrush.draw(mCanvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(event);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up(event);
invalidate();
break;
}
return true;
}
}
Edit: snap shot (Raghunandan). Result Testing with White Background and Black Color paint.
Found the solution.
For those who might be interested:
public class DrawView extends View {
public Paint mPaint;
private Paint mPaint1;
private Paint mPaint2;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public DrawView(Context context, AttributeSet attrs) {
super( context, attrs);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAlpha(0x80);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0x44000000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.BUTT);
mPaint.setStrokeWidth(5);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFF00B8F5);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
//mCanvas.drawPoint(x, y, mPaint);
}
private void touch_move(MotionEvent event) {
float x = event.getX();
float y = event.getY();
Path npath=new Path();
npath.moveTo(mX, mY);
npath.lineTo( x ,y );
mX=x;
mY=y;
mCanvas.drawPath(npath, mPaint);
npath.reset();
//Log.e("","sto disegando");
}
private void touch_up() {
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(event);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
Edit: Attaching snap shot of my emulator (Raghunandan). I used your code no changes except increased the stroke width and it looks like below.
Does not look good when you draw slowly.
Screen shot stroke width 12 if you draw a striaght line no problem. But when you draw zig zag you can see it does not look good

How to make black background and red color for drawing?

I have been developing the application for drawing. I have following code for main activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
Display display = getWindow().getWindowManager().getDefaultDisplay();
mMainView = new MyView(this, display.getWidth(), display.getHeight());
setContentView(mMainView);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
And code for my custom view for drawing:
public class MyView extends View {
private static final float TOUCH_TOLERANCE = 4;
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private float mX, mY;
public MyView(Context context, int width, int height) {
super(context);
this.setDrawingCacheEnabled(true);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFF000000);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
public void clearView() {
mBitmap.eraseColor(Color.TRANSPARENT);
}
public Bitmap getState() {
return mBitmap;
}
private void touchStart(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
invalidate();
break;
}
return true;
}
}
So, because if I try to save resulted bitmap as jpeg file using bitmap compress then all is good, but if I try to save as png file I will get file with transparent background (white) and red picture. I need that I can save using JPEG/PNG with black background and red picture. Code for saving is good, don't worry. Thank you.
you can draw a black rectangle on the bitmap, like so:
Bitmap myBitmap = Bitmap.createBitmap(width, height, ...);
Canvas mCanvas = new Canvas(myBitmap);
// create a black rectangle
final int color = 0xffffffff;
final Paint p1 = new Paint();
final Rect rect = new Rect(0, 0, width, height);
final RectF rectF = new RectF(rect);
// draw it to the canvas
mCanvas.drawARGB(0, 0, 0, 0);
p1.setColor(color);
mCanvas.drawRect(rectF, p1);
That should force a black background, and you can overlay additional bitmaps on the canvas, and finally use myBitmap to export as png.
I think the black background you have now is a jpeg default, since it does not have transparency.

Categories