I've been working on this for a while. This code:
Log.i(TAG, "stroke style: " + paint.getStyle());
Log.i(TAG, "stroke cap: " + paint.getStrokeCap());
canvas.drawPoint(p.x, p.y, paint);
prints 'STROKE' and 'ROUND' to the logs, but draws a black SQUARE to the map! Anyone know what I need to be doing differently to produce a dot instead of a square!?
Thanks!
EDIT
I'm going to give the below suggestion(s) of using drawCircle a shot, but I was just confused I guess because everything I've read indicates you should be able to indicate you want a circle that way. One example being this google book entry
Try to use drawCircle instead
circlePaint.setStyle(Style.FILL);
circlePaint.setAntiAlias(true);
circlePaint.setColor(0xFFFF0000); //opaque red
float radius = 10f; //10 pixels
canvas.drawCircle(p.x, p,y, radius, circlePaint);
you can try drawCircle() with p.x and p.y as center (first and second argument) and use 1 or 2 as radius depend on how big you want the dot to be and use the paint with stroke style FILL..
It draws correctly if you draw to a canvas backed by a bitmap. It doesn't seem to draw correctly if you draw directly to the screen (i.e. a canvas passed to a View's onDraw() method). Another way of getting around the problem is, therefore, to first render to a bitmap and then draw that to the screen.
Related
I am trying to draw a heart shaped Canvas using Path in Android. The code is as follows :
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Fill the canvas with background color
canvas.drawColor(Color.WHITE);
// paint.setShader(null);
// Defining of the heart path starts
path.moveTo(left + WIDTH / 2, top + HEIGHT / 4); // Starting point
// Create a cubic Bezier cubic left path
path.cubicTo(left+WIDTH/5,top,
left+WIDTH/4,top+4*HEIGHT/5,
left+WIDTH/2, top+HEIGHT);
// This is right Bezier cubic path
path.cubicTo(left + 3 * WIDTH / 4, top + 4 * HEIGHT / 5,
left + 4 * WIDTH / 5, top,
left + WIDTH / 2, top + HEIGHT / 4);
paint.setShader(new LinearGradient(0, canvas.getHeight()/4, canvas.getWidth(), canvas.getHeight()/4, new int[]{Color.RED, Color.YELLOW, Color.GREEN}, new float[]{0, 0.6f, 1}, Shader.TileMode.CLAMP));
canvas.drawPath(path, paint);
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(4);
heart_outline_paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, heart_outline_paint);
}
I am able to draw heart without any issue and I am able to fill color inside the heart using the Fill option in Paint. But I should be able to fill the heart dynamically according to some data and it cannot be filled fully all the time. What I have achieved so far is as follows :
I have made an extensive search and came across a lot of things similar to this. Some of which includes :
Android fill in part of a path?
filling a circle gradually from bottom to top android
I also came across the concept of converting the canvas to bitmap and filling color inside the bitmap using Flood Fill Algorithm which lets users to fill colors inside the bitmap. However, I do not want the bitmap to fill the color while touching inside the heart but to fill while a button click action.
I thought that filling a circle gradually from bottom to top android
would give help me but it makes use of a circle and I am not well-versed in Canvas which makes me very weak in adapting the circle code to such a shape.
If anybody has some ideas or any insights on how to achieve this, it will be really helpful. Cheers. Thanks in advance.
P.S : I also tried some tricks using setShader in Paint but nothing would give me what I want.
EDIT :
I just stumbled upon a idea of drawing a rectangle over the heart with another color same as the background of the canvas so that it will look like its half filled !! I am still working on the idea and not sure how accurate this is gonna be for me. If someone has a better idea, you're most welcome.
I used clipPath function available in Canvas to achieve what I needed. I draw the heart by above method and draw a rectangle over it, and I use the clipPathfunction to clip out the region that is outside the heart.
public static double filled_amount = .90;
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.cubicTo(right_x2, right_y2, right_x1, right_y1, left_x_moveto, left_y_moveto);
path.close();
Rect rect = new Rect((int)(canvas.getWidth()*.10),(int)(canvas.getHeight()*filled_amount),(int) canvas.getWidth(), (int) canvas.getHeight());
canvas.clipPath(path);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
canvas.drawRect(rect, rect_paint);
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, heart_outline_paint);
This will give me the desired result of filling the heart dynamically. Changing the value of filled_amount dynamically and calling invalidate() will make it look like the heart is being filled dynamically.
#Henry's answer might be a better one but this did the trick for me and I dont look deeply in to the edges so a bit of zig-zags here and there is all right.
You could use Bitmap Masking to get a partially filled Heart. What you ideally do here is use one bitmap to mask the other.
In your case you could have a filled rectangle in the canvas and you have then have the heart shape in a new bitmap to act as the mask. You could then dynamically change the filling of the heart by changing the height of the background rectangle.
Refer this: https://stackoverflow.com/a/33483600/4747587. This contains the implementation of partially filling a Star. The idea is the same.
I am drawing an arc with a border by painting two arcs, one over the other the first being slightly larger.
The issue is with "slightly larger" this can end up with the border not always being even all the way round.
Both the arcs I am drawing have the same radius, I simply make it larger by adding a degree to the start and two degrees to the end (necessary to ensure the borders on either end of the arc are equal) and increasing the stroke width.
In the supplied picture the thicker border edge is the smallest I can possibly make it while it is still visible. (-1 degree off the inner arc)
I have considered drawing the arc outline with four separate calls two straight lines for either end and two arcs. This seems quite inefficient for what I want to achieve.
I am wondering if anyone has any suggestions about how else I could draw a border thats even, minimizing the number of draw/canvas rotation calls if possible.
Relevant code sample for current solution:
Paint mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setStyle(Style.STROKE);
mFillPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mFillPaint.setColor(Color.TRANSPARENT);
mFillPaint.setStrokeWidth(mValueWidth);
mOutlinePaint.setStyle(Style.STROKE);
mOutlinePaint.setStrokeWidth(mBorderWidth);
mOutlinePaint.setColor(Color.WHITE);
mRect.set(mHalfXSubRadius, mHalfYSubRadius, mHalfXAddRadius, mHalfYAddRadius);
canvas.drawArc(mRect, ARC_START-1, MAX_ARC+2, false, mOutlinePaint);
canvas.drawArc(mRect, ARC_START, MAX_ARC, false, mFillPaint);
U shouldnt make your arc bigger, instead try to draw the same sized arc (in white), X pixel right,down,up,left,corners as well (total of 8 drawings).
where X is the border size u want.
after that draw the main arc (in gray) in the middle.
psuedo code:
paint=white;
drawArc(x,y+2);
drawArc(x,y-2);
drawArc(x+2,y+2);
drawArc(x+2,y-2);
drawArc(x-2,y+2);
drawArc(x-2,y+2);
drawArc(x+2,y);
drawArc(x-2,y);
paint=gray;
drawArc(x,y);
I want a cylindrical, spider web like layout:
I know that I can use canvas to draw this but I also need all portions to be clickable, and canvas is very hard to handle touch for all portion.
Ideas?
can i want layout like spider...
Yes you can want it. But if you want to actually create that layout then you cannot do it with the standard android widgets.
If you want to make it then I would suggest drawing it on a Canvas manually and using the onTouchListener to catch the key presses.
I am not sure but i hope this can help you ...
The Path class holds a set of vector-drawing commands such as lines,
rectangles, and curves. Here’s an example that defines a circular path:
circle = new Path();
circle.addCircle(150, 150, 100, Direction.CW);
This defines a circle at position x=150, y=150, with a radius of 100
pixels. Now that we’ve defined the path, let’s use it to draw the circle’s
outline plus some text around the inside:
private static final String QUOTE = "Now is the time for all " +
"good men to come to the aid of their country." ;
canvas.drawPath(circle, cPaint);
canvas.drawTextOnPath(QUOTE, circle, 0, 20, tPaint);
You can see the result in this Figure
If you want to get really fancy, Android provides a number of PathEffect
classes that let you do things such as apply a random permutation to a
path, cause all the line segments along a path to be smoothed out with
curves or broken up into segments, and create other effects.
I am trying to draw a white circle with the following code:
mPaint.setColor(0xFFFFFFFF);
canvas.drawCircle(x, y, radius, mPaint);
But it is being displayed as a solid disk. How do I get it to just display as a circular outline with a transparent centre?
I've had a look in the help and it makes no sense to me, probably because I'm not used to the drawing terms like stroke and dither. What's wrong with background and border, eh?
I suspect you want:
mPaint.setStyle(Paint.Style.STROKE);
so that it doesn't do the filling. But then again, I've never used the Android API - this is really just a guess based on the docs :)
When I call drawCircle (ex. canvas.drawCircle(x, y, r, mPaint);) and I use Paint Style STROKE to initialize the parameter mPaint, the result doesn't quite make a full 360 degrees (2*PI radian) circle in all cases. Sometimes you get a full circle (as I would expect) and sometimes only an arc.
Does someone have an idea what would cause this to happen ?
I don't know what cases work and which don't (yet). I've noticed the ones that don't work seem to be the larger circles I'm drawing (>100.0 radius). Could be size related. I am using floating point for x, y and r. I could try rounding to the nearest int when in the drawing code.
Are you doing anything else to the canvas before the drawCircle? This could happen if, for example you are scaling the canvas or transforming it before you draw the circle.