Wrong Stroke width drawing circle on custom view Android - android

I am writing a custom view in android. I want to draw a circle that cover all width and height of my view. this is my code
private void init() {
bgpaint = new Paint();
bgpaint.setColor(bgColor);
bgpaint.setAntiAlias(true);
bgpaint.setStyle(Paint.Style.STROKE);
bgpaint.setStrokeWidth(strokeWidth);
rect = new RectF();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw background circle anyway
int strokeWidth = 50;
rect.set(strokeWidth, strokeWidth, getwidth()- strokeWidth,
getheight() - strokeWidth);
canvas.drawArc(rect, -90, 360, fill, bgpaint);
}
But when I run result will be like this
I want be like this
What the problem with my code?

Probem is in setting your rectangle's coordinates. You must set half of stroke width, not whole stroke width.
float left=strokeWidth / 2;
float top=strokeWidth / 2;
float right=minDimen - strokeWidth/ 2;
float bottom=minDimen - strokeWidth / 2;
rect.set(left, top, right,bottom);
Because it comes to circle, I assume your width and height of your circleView are the same dimension. That is minDimen in my code. Because I use smaller dimension of those two.
final int minDimen = Math.min(width, height);
setMeasuredDimension(minDimen, minDimen);
(this must be called in onMeasure method)
Anyway, it's good method to set width and height in same dimensions.

Related

Android PorterDuff: Why doesn't PorterDuff.Mode.SRC_IN cut out the rest of the source?

I'm trying to use the PorterDuff library to trim a canvas circle and rectangle to form a quarter of a square in my custom view for my app, I managed to get it to work but not fully because it trims the square out but keeps the rest of the circle in, I'm using the SRC_IN mode which seems like the right mode to use from looking at the android documentation for it but it's not working as expected, this is a snippet of the onDraw method in my custom view class:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
canvas.drawCircle(width / 2, height / 2, (width + height) / 10, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Rect rectangle = new Rect(0, 0, width / 2, height / 2);
paint.setColor(Color.RED);
canvas.drawRect(rectangle, paint);
}
I'm drawing the circle in the center of the screen and then drawing the square in the top left of the screen and the PorterDuff mode should basically get the intersected part between the shapes but it just trims non-intersected square part out but doesn't do the same for the circle.
This is what it looks like:
I can't tell what i'm doing wrong here, hopefully someone can point it out.
the issue is with the source, the rectangle is the source in this context, draw the rectangle first then use PorterDuff.Mode.SRC_IN to cut the circle based on it.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
Rect rectangle = new Rect(0, 0, width / 2, height / 2);
paint.setColor(Color.RED);
canvas.drawRect(rectangle, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawCircle(width / 2, height / 2, (width + height) / 10, paint);
}

Animation not fluent Android Wear

I'm starting with Android Wear and I want to make a circle animation, making grow.
I know how to do it, I think, but it's doing it very very slow, hope you can help me
I have this class variable
Paint mAnimation;
intialized on the method OnCreate
mAnimation = new Paint(Paint.ANTI_ALIAS_FLAG);
mAnimation.setStyle(Paint.Style.FILL);
mAnimation.setColor(Color.GREEN);
and on the OnDraw method I have
#Override
public void onDraw(Canvas canvas, Rect bounds) {
int width = bounds.width();
int height = bounds.height();
float centerX = width / 2f;
float centerY = height / 2f;
// Draw the background.
canvas.drawRect(0, 0, bounds.width(), bounds.height(), mBackgroundPaint);
canvas.drawCircle(0, centerY, radiusPlus, mAnimation);
radiusPlus += 20;
}
The animation is "correct", but is very slow, like if was paused.
Thanks!!
EDIT
I found a example and now I finally found why. I didn't invalidate the view at the end of the OnDraw. Now It's working fine. Thanks.
#Override
public void onDraw(Canvas canvas, Rect bounds) {
int width = bounds.width();
int height = bounds.height();
float centerX = width / 2f;
float centerY = height / 2f;
// Draw the background.
canvas.drawRect(0, 0, bounds.width(), bounds.height(), mBackgroundPaint);
canvas.drawCircle(0, centerY, radiusPlus, mAnimation);
radiusPlus += 5;
if (isVisible() && !isInAmbientMode()) {
invalidate();
}
}

scaling from rectangle to square

I newbie to android and graphic development.
I implement a custom-view and want to draw to canvas.
I set the customview size to be (width x (width/2)) so the rectangle height is half of the width.
Now when start drawing, its easy for me to draw on a square area like 1X1.
like this:
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int ChosenSize = Math.min(widthSize, heightSize);
int width = ChosenSize;
int height = (int)(ChosenSize/2);
setMeasuredDimension(width,height);
}
#Override protected void onDraw(Canvas canvas){
float width = (float)getWidth();
float height = (float)getHeight();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(width ,height );
// start drawing in a 1X1 square coordinates
canvas.restore();
}
But after restore() the result is stretched a little bit.
What am i doing wrong ??
Note: I have notice that when not using scale and working with the rectangle width and height the
result looks Ok
Thx
I figure it out.
The reason my drawing stretch, is because I scale from rectangle to square which is mistake.
Usually when canvas is square it easy to draw on 1x1 square, so I scale to canvas.scale(width,height),
But when canvas is rectangle like (width,width/2), I should scale to (width,height/width) to get rect of 1x2.
so after I change scaling to canvas.scale(width,height/width)

Drawable: Understanding canvas width and height

I try to implement my own drawable that will corss fade from a simple colored rectangle (that should have the same size as the ImageView where the drawable is in) to a loaded bitmap (over http).
So what I do is override the draw() method of my Drawable:
public void draw(Canvas canvas) {
boolean done = true;
Log.d("Test",
"canvas w: " + canvas.getWidth() + " " + canvas.getHeight());
final int alpha = mAlpha;
final boolean crossFade = mCrossFade;
Paint paint = mStartPaint;
paint.setColor(blueColor);
if (!crossFade || 255 - alpha > 0) {
if (crossFade) {
paint.setAlpha(255 - alpha);
}
// Draw the rect with the color
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
if (crossFade) {
paint.setAlpha(0xFF);
}
}
if (alpha > 0) {
Bitmap bitmap = mEnd;
paint = mEndPaint;
paint.setAlpha(alpha);
if (mBitmapScalingType == null)
canvas.drawBitmap(bitmap, mEndX, mEndY, paint);
else
mBitmapScalingType.draw(bitmap, canvas.getWidth(),
canvas.getHeight(), canvas, paint);
paint.setAlpha(0xFF);
}
if (!done) {
mHandler.post(mInvalidater);
}
}
So the canvas.getWidth() and canvas.getHeight() returns 128 (width) and 150 (height) which is the same as the ImageView has. But the result is:
The blue rectangle has not been painted over the complete canvas and I can't get figure out why.
The ImageView that displays my fadeable drawable has no specific scaletype set.
Any ideas what could be wrong?
I have also noticed that the width and height calculated from setBounds() is 180 x 212 px
#Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
final int width = right - left;
final int height = bottom - top;
Log.d("Test", "width: "+width+" height: "+height);
}
and if I draw the color with 180 x 212 px
canvas.drawRect(0, 0, 180, 212, paint);
the rectangular is now drawn to fill the canvas completely.
Any idea what could be wrong?
Btw. The ImageView is defined like that:
<ImageView android:id="#+id/playerPic"
android:layout_width="64dp"
android:layout_height="75dp"
android:layout_marginRight="10dp"
/>
in xhdpi 64dp = 128px and 75dp = 150 px
This answer doesn't explain the difference in dimensions, but sometimes it's easier to just do things a different way.
If you just want to fill the canvas with a color, you don't need to use drawRect(), just use drawColor(). There's the simple version that just takes a Color, and one that lets you specify a porter-duff mode. This way you don't need dimensions at all, and you can avoid the whole thing.
Maybe you can try to use DisplayMetrics to get the dimensions.
//Get the width and height of the screen
DisplayMetrics d = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(d);
int width = d.widthPixels;
int height = d.heightPixels;
Then just call drawrect with those values
canvas.drawRect(0, 0, width, height, paint);

Android subpixel rendering

I have a line that should get thinner the longer it gets. The problem is, that you can clearly see a jump when it gets a pixel thinner. Is there a way to do subpixel rendering/antialiasing on Android?
canvas.drawRect() takes float values, but it's ignoring those. Here's the code:
#Override
protected void onDraw(Canvas canvas) {
float width = getMeasuredWidth() / (float) getMeasuredHeight() * getMinimumHeight();
float left = (getMeasuredWidth() - width) / 2.0f;
canvas.drawRect(left, 0, left + width, getMeasuredHeight(), paint);
super.onDraw(canvas);
}
The paint object has ANTI_ALIAS_FLAG enabled and contains a solid color.
This is the default line:
This is when it gets longer and thinner. It should have some anti aliasing on the sides, though to make the whole transition seems smoother.
This seems to do a better job:
#Override
protected void onDraw(Canvas canvas) {
float width = getMeasuredWidth() / (float) getMeasuredHeight() * getMinimumHeight();
float left = (getMeasuredWidth() - width) / 2.0f;
paint.setStrokeWidth(width * getResources().getDisplayMetrics().density);
canvas.drawLine(left, 0, left, getMeasuredHeight(), paint);
super.onDraw(canvas);
}

Categories

Resources