public static Bitmap getCircularBitmapWithWhiteBorder(Bitmap bitmap,
int borderWidth) {
if (bitmap == null || bitmap.isRecycled()) {
return null;
}
final int width = bitmap.getWidth() + borderWidth;
final int height = bitmap.getHeight() + borderWidth;
Bitmap canvasBitmap = Bitmap.createBitmap(width*2, height, Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
Canvas canvas = new Canvas(canvasBitmap);
float radius = width > height ? ((float) height) / 2f : ((float) width) / 2f;
canvas.drawCircle(width / 2, height / 2, radius, paint);
paint.setShader(null);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(borderWidth);
canvas.drawCircle(width / 2, height / 2, radius - borderWidth / 2, paint);
return canvasBitmap;
}
I have circular image, i want to attach next to circular image sort of a rectangle..similar to his
this is a circle, next to it there is a rectangle attached. how can I do this?
You could draw your Rectangle more or less like this:
canvas.drawRect(width/2 + radius, height/2 - radius, width , height, paint);
just adjust the parameters for positioning it correctly if needed
Related
I am trying to convert text into image using below code :
public Bitmap textAsBitmap(String text, float textSize) {
Paint paint = new Paint(ANTI_ALIAS_FLAG);
paint.setTextSize(textSize);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setTextAlign(Paint.Align.CENTER);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(text) + 0.5f); // round
int height = (int) (baseline + paint.descent() + 0.5f);
Bitmap image = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawText(text, 0, baseline, paint);
return image;
}
Its convert text into image but problem is show half text.It should show "favorite subject is english"!
what i am doing wrong ? or how should i solve this problem
Choose your width & height wisely,
Something like I did in my case
public Bitmap textAsBitmap(String text, float textSize) {
Paint paint = new Paint(ANTI_ALIAS_FLAG);
paint.setTextSize(textSize);
paint.setColor(Color.BLACK);
paint.setTextAlign(Paint.Align.LEFT);
float baseline = -paint.ascent(); // ascent() is negative
int width = (int) (paint.measureText(text) + 0.0f); // round
int height = (int) (baseline + paint.descent() + 0.0f);
int actualWidth = width;
if (width > height)
height = width;
else
width = height;
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawText(text, width / 2 - actualWidth / 2, baseline, paint);
return image;
}
Problem is with paint.setTextAlign(Paint.Align.CENTER);, this property considers center as (0,0). So your text is actually at center according to (0,0).
Just remove paint.setTextAlign(Paint.Align.CENTER); and your code is working!!
Here is what I'm using to draw a circle shape on to the canvas (and then an icon bitmap on it):
private static Bitmap makeIcon(int radius, int color, Bitmap icon) {
final Bitmap output = Bitmap.createBitmap(radius, radius, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(color);
canvas.drawARGB(0, 0, 0, 0);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
canvas.drawCircle(radius / 2, radius / 2, radius / 2, paint);
else
canvas.drawRect(0, 0, radius, radius, paint);
int cx = (radius - icon.getWidth()) >> 1; // same as (...) / 2
int cy = (radius - icon.getHeight()) >> 1;
canvas.drawBitmap(icon, cx, cy, paint);
icon.recycle();
return output;
}
But I have no idea on how to draw a squircle shape instead of the circle shape. FYI, here are some examples of icons using the squircle shape:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path squirclePath = getSquirclePaath(150, 250, 400);
canvas.drawPath(squirclePath, mPaint);
}
private static Path getSquirclePaath(int left, int top, int radius){
//Formula: (|x|)^3 + (|y|)^3 = radius^3
final double radiusToPow = radius * radius * radius;
Path path = new Path();
path.moveTo(-radius, 0);
for (int x = -radius ; x <= radius ; x++)
path.lineTo(x, ((float) Math.cbrt(radiusToPow - Math.abs(x * x * x))));
for (int x = radius ; x >= -radius ; x--)
path.lineTo(x, ((float) -Math.cbrt(radiusToPow - Math.abs(x * x * x))));
path.close();
Matrix matrix = new Matrix();
matrix.postTranslate(left + radius, top + radius);
path.transform(matrix);
return path;
}
Here is a preview:
The other way is to use a BitmapShader.
Note: both mask and image must be equal size, so you have to resize your images.
Note2: this code is developed for Launcher icons and has poor Adaptive Icons adaptation yet.
baseIconSize is a «destination» size.
fun Drawable.toBitmap(width: Int, height: Int, config: Bitmap.Config): Bitmap {
val bitmap = Bitmap.createBitmap(width, height, config)
val canvas = Canvas(bitmap)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (this is AdaptiveIconDrawable) {
background.setBounds(0, 0, width, height)
background.draw(canvas)
foreground.setBounds(0, 0, width, height)
foreground.draw(canvas)
} else {
setBounds(0, 0, width, height)
draw(canvas)
}
} else {
setBounds(0, 0, width, height)
draw(canvas)
}
return bitmap
}
val maskBitmap = requireNotNull(context.getDrawable(R.drawable.mask_squircle))
.toBitmap(
width = baseIconSize,
height = baseIconSize,
config = Bitmap.Config.ALPHA_8
)
val iconBitmap = Bitmap.createBitmap(
baseIconSize,
baseIconSize,
Bitmap.Config.ARGB_8888
)
val originalBitmap = if (bitmap.width == baseIconSize && bitmap.height == baseIconSize) {
bitmap
} else {
bitmap.scale(baseIconSize, baseIconSize)
}
iconShapePaint.shader = BitmapShader(
originalBitmap,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT
)
val canvas = Canvas(iconBitmap)
canvas.drawBitmap(maskBitmap, 0f, 0f, iconShapePaint)
originalBitmap.recycle()
return iconBitmap
Before:
After:
Mask:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1024dp"
android:height="1024dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M512,1024C736.36,1024 861.08,1024 942.54,942.54C1024,861.08 1024,736.36 1024,512C1024,287.64 1024,162.92 942.54,81.46C861.08,0 736.36,0 512,0C287.64,0 162.92,0 81.46,81.46C0,162.92 0,287.64 0,512C0,736.36 0,861.08 81.46,942.54C162.92,1024 287.64,1024 512,1024Z"
android:strokeWidth="1"
android:fillColor="#000000"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
This question already has answers here:
How to draw text on canvas?
(3 answers)
Closed 8 years ago.
I am writing an application that consists of a gauge view. I downloaded from here and i want to draw text inside the gauge view (that is at the center of the gauge view) how can i draw a text inside a gauge view please help me.
After my friends answers in stack overflow i did it like this but it did not works please make it work
private void drawGauge()
{
if (null != mBackground)
{
mBackground.recycle();
}
/*--For Semi circle put getHeight()/2--*/
mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
newBitmap = Bitmap.createBitmap(mBackground.getWidth(), mBackground.getHeight(), Config.ARGB_8888);
Canvas newCanvas = new Canvas(newBitmap);
final Canvas canvas = new Canvas(mBackground);
final float scale = Math.min(getWidth(), getHeight());
canvas.scale(scale, scale);
canvas.translate((scale == getHeight()) ? ((getWidth() - scale) / 2) / scale : 0,(scale == getWidth()) ? ((getHeight() - scale) / 2) / scale : 0);
Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setColor(Color.WHITE);
paintText.setTextSize(50);
paintText.setTextAlign(Align.CENTER);
paintText.setStyle(Style.FILL);
Rect rectText = new Rect();
paintText.getTextBounds(captionString, 0, captionString.length(), rectText);
newCanvas.drawText(captionString, 0, rectText.height(), paintText);
//canvas.drawText("MedeQuip", 200, 500, shadowpaint);
//drawRim(canvas);
//drawFace(canvas);
For vipluv:
protected void onDraw(final Canvas canvas) {
drawBackground(canvas);
final float scale = Math.min(getWidth(), getHeight());
canvas.scale(scale, scale);
canvas.translate((scale == getHeight()) ? ((getWidth() - scale) / 2) / scale : 0, (scale == getWidth()) ? ((getHeight() - scale) / 2) / scale : 0);
if (mShowNeedle) {
drawNeedle(canvas);
}
if (mShowText) {
drawText(canvas);
}
Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setColor(Color.WHITE);
paintText.setTextSize(150);
paintText.setTextAlign(Align.CENTER);
paintText.setStyle(Style.FILL);
Rect rectText = new Rect();
paintText.getTextBounds(captionString, 0, captionString.length(), rectText);
canvas.drawText(captionString, rectText.width(), rectText.height(), paintText);
computeCurrentValue();
}
In the onDraw() function in their GaugeView.java file, add a canvas.drawText() just before the call to computeCurrentValue().
Use your own Paint object, and make sure you have initialized its textsize and color properties.
public static Bitmap drawCircle(int width,int height, int borderWidth) {
Bitmap canvasBitmap = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(canvasBitmap, TileMode.CLAMP,
TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
paint.setShader(null);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(borderWidth);
Canvas canvas = new Canvas(canvasBitmap);
float radius = width > height ? ((float) height) / 2f : ((float) width) / 2f;
canvas.drawCircle(width / 2, height / 2, radius - borderWidth / 2, paint);
return canvasBitmap;
}
Simple this code draws a circle with white border, however I want part of the border to be black and the other part white. 40 % of it black, 60 % of it white
How can this be done?
Try this code
class MyView extends View
{
private Paint paint;
public MyView(Context context, int x, int y)
{
super(context);
paint = new Paint();
// PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
paint.setAlpha(255);
// paint.setXfermode(xfermode);
paint.setAntiAlias(true);
// setBackgroundColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawCircle(100, 100, 50, paint);
}
}
Here a utility method for filling a circle with one color and stroking the circle border with another color.
Use the second method to pass in an existing Paint instance, e.g. to set the anti-alias flag or to prevent memory allocations during onDraw().
public static void fillCircleStrokeBorder(
Canvas c, float cx, float cy, float radius,
int circleColor, float borderWidth, int borderColor) {
fillCircleStrokeBorder(c, cx, cy, radius, circleColor, borderWidth, borderColor, new Paint());
}
public static void fillCircleStrokeBorder(
Canvas c, float cx, float cy, float radius,
int circleColor, float borderWidth, int borderColor, Paint p) {
int saveColor = p.getColor();
p.setColor(circleColor);
Paint.Style saveStyle = p.getStyle();
p.setStyle(Paint.Style.FILL);
c.drawCircle(cx, cy, radius, p);
if (borderWidth > 0) {
p.setColor(borderColor);
p.setStyle(Paint.Style.STROKE);
float saveStrokeWidth = p.getStrokeWidth();
p.setStrokeWidth(borderWidth);
c.drawCircle(cx, cy, radius - (borderWidth / 2), p);
p.setStrokeWidth(saveStrokeWidth);
}
p.setColor(saveColor);
p.setStyle(saveStyle);
}
Just draw your circle at full size with one color, then draw the circles again at the same coordinate, but with a different color and with a smaller radius, and scale down the radius however much you need to, that would be the most trivial way to do it.
I want to draw circle in center of screen, but I'm getting something like this:
I'm using this code to draw this circle.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(bmp);
RectF rect = new RectF(0,0,width,width);
drawCircle(rect, c, width, height);
ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setImageBitmap(bmp);
img.setScaleType(ScaleType.FIT_CENTER);
}
private void drawCircle(RectF rect, Canvas c, int width, int height) {
Paint paint = new Paint();
paint.setARGB(255, 255 , 10, 21);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStyle(Paint.Style.STROKE);
int radius;
if(width < height)
radius = width/2;
else
radius = height/2;
c.drawCircle(width/2, height/2, radius, paint);
}
I don't understand why it's cut at sides even though I use size of screen to draw it, so it should perfectly fit it.
You didn't account for the thickness of the line (strokeWidth). You drew a circle assuming it had 0 thickness, so the "actual" circle IS touching the edges of the screen, but since you used a thick paintbrush, some of the paint leaked past the edge.
you should decrease the thickness/2.
private void drawCircle(RectF rect, Canvas c, int width, int height) {
Paint paint = new Paint();
paint.setARGB(255, 255 , 10, 21);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStyle(Paint.Style.STROKE);
int radius;
if(width < height)
radius = width/2;
else
radius = height/2;
//this is the new line:
radius-= 5;
c.drawCircle(width/2, height/2, radius, paint);
}
Account for the StrokeWidth in the radius:
// Substract stroke width.
radius -= paint.getStrokeWidth() / 2;
c.drawCircle(width/2, height/2, radius, paint);