I'm overriding View on Android to do some custom drawing, but the rendered view has not very good quality, especially the text. I have found a couple of solutions, but none worked for me. Attaching the code here. Thank you for any help.
#Override
protected void onDraw(Canvas canvas) {
int width = canvas.getWidth();
int height = canvas.getHeight();
Point a = new Point(0, 0);
Point b = new Point(width / 2, height);
Point c = new Point(width, 0);
Path trianglePath = new Path();
trianglePath.moveTo(a.x, a.y);
trianglePath.lineTo(b.x, b.y);
trianglePath.lineTo(c.x, c.y);
trianglePath.lineTo(a.x, a.y);
Paint paint = new Paint();
paint.setStrokeWidth(1);
paint.setColor(Color.parseColor("#7A7A7A"));
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
canvas.drawPath(trianglePath, paint);
Paint textPaint = new Paint();
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(height / 6);
textPaint.setTypeface(TypefaceUtils.getTypeface(getContext(), TypefaceUtils.AVAILABLE_FONTS.ROBOTO_THIN));
String receive = getContext().getString(R.string.receive_password).split("\n")[0];
String password = getContext().getString(R.string.receive_password).split("\n")[1];
Rect receiveBounds = new Rect();
Rect passwordBounds = new Rect();
textPaint.getTextBounds(receive, 0, receive.length(), receiveBounds);
textPaint.getTextBounds(password, 0, password.length(), passwordBounds);
canvas.drawText(
receive,
(width - receiveBounds.width()) / 2,
height / 3 - receiveBounds.height() + receiveBounds.height() / 5,
textPaint);
canvas.drawText(
password,
(width - passwordBounds.width()) / 2,
height / 3 + receiveBounds.height(),
textPaint);
canvas.scale(1, 1);
}
Try setting textpaint.setAntiAlias(true);
Related
I am using following code to make a spinner wheel.
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
for (int i = 0; i < segmentColors.length; i ++)
{
drawDataSet(canvas, i);
}
canvas.drawCircle(getWidth()/2, getHeight()/2, getWidth() - getWidth()/2 - dpToPx(5), mTransparentCirclePaint);
}
protected void drawDataSet(Canvas canvas, int position)
{
int color = segmentColors[position];
float mainArcAngle = ((float) 360/ (float)segmentColors.length);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
if ( position%2 == 0)
paint.setColor(color);
else
paint.setColor(Color.parseColor("#009f2f"));
RectF rect = new RectF(0, 0, getWidth(), getWidth());
canvas.drawArc(rect, (mainArcAngle * position), mainArcAngle, true, paint);
TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setAntiAlias(true);
mTextPaint.setTypeface(Typeface.MONOSPACE);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(18f);
Path path = new Path();
path.addArc(rect, (mainArcAngle * position), mainArcAngle);
//PathMeasure pm = new PathMeasure(path, false);
//DynamicLayout layout = new DynamicLayout(values[position], values[position], mTextPaint, (int) pm.getLength(), Layout.Alignment.ALIGN_CENTER, 1, 0, true);
//canvas.save();
//layout.draw(canvas);
//canvas.restore();
canvas.drawTextOnPath(values[position], path, 0 , getWidth() / 6 , mTextPaint );
}
The text that is written inside the arc is a bit compressed because of small spacing. How can I make it multiline or increase letter spacing?
Starting from API 21 you can use Paint#setLetterSpacing(float):
Set the paint's letter-spacing for text. The default value is 0. The value is in 'EM' units. Typical values for slight expansion will be around 0.05. Negative values tighten text.
You may also see how TextView#setLetterSpacing() is implemented.
I have been trying to make a photo sharing app, with the ability to add your image and name to the image. I have been messing with Canvas for the whole day, but couldn't get good results. I was able to draw the name and bitmap, but they didn't look so good.
That's why I am here asking about is there any library or piece of code that could help me in making something similar to [this][1]. I wasn't able to find any thing for it.
EDIT: Sorry for not adding my own code
Here is my code from my latest try
public void AddText(Position2D pos){
//Position2D is an enum having the 4 corners of the image
bmWorking= bmOriginal.copy(Bitmap.Config.ARGB_8888,true);
Canvas canvas = new Canvas(bmWorking);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
Paint textPaint = new Paint();
textPaint.setColor(Color.BLACK);
float width = (35f/100f) * bmWorking.getWidth();
float height = (width/16f) * 3;
textPaint.setTextSize(height - 4); //I wanted to have some space (margin) above and below the text
textPaint.setTextAlign(Paint.Align.LEFT);
float [] coords = getPositionCoords(pos, width, height); //getPositionCoords returns a float array with the Left,Top,Right,Bottom position calculated based on the width and height
canvas.drawRect(coords[0],coords[1], coords[2], coords[3],paint);
username = "Haider Ali Punjabi";
canvas.drawText(username, coords[0] ,coords[3], textPaint);
bitmapView.setImageBitmap(bmWorking);
}
Here is the result
UPDATE:
#pskink gave me this code
which works nicely
if you want to customize it, then instead of solid white rectangle (like in your original code) use a Drawable and the result could be something like this:
the code:
// for int gravity: see android.view.Gravity, like Gravity.LEFT, Gravity.BOTTOM, etc
// for example:
// Bitmap out = addText(this, in, "Haider Ali Punjabi", android.R.drawable.alert_light_frame, Gravity.BOTTOM, new Point(10, 10));
public Bitmap addText(Context ctx, Bitmap in, String text, int resId, int gravity, Point pad) {
if (pad == null) pad = new Point();
Bitmap out = in.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(out);
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(Color.BLACK);
textPaint.setTextAlign(Paint.Align.LEFT);
// textPaint.setTextSize(128);
Rect inBounds = new Rect();
textPaint.getTextBounds(text, 0, text.length(), inBounds);
float scale = out.getWidth() * 0.35f / inBounds.width();
Rect container = new Rect(0, 0, out.getWidth(), out.getHeight());
Rect outBounds = new Rect();
int w = (int) (inBounds.width() * scale);
int h = (int) (inBounds.height() * scale);
Gravity.apply(gravity, 2 * pad.x + w, 2 * pad.y + h, container, outBounds);
Drawable dr = ctx.getResources().getDrawable(resId);
Rect padding = new Rect();
dr.getPadding(padding);
dr.setBounds(outBounds.left - padding.left, outBounds.top - padding.top, outBounds.right + padding.right, outBounds.bottom + padding.bottom);
dr.draw(canvas);
Matrix matrix = new Matrix();
RectF src = new RectF(inBounds);
RectF dst = new RectF(outBounds);
dst.inset(pad.x, pad.y);
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
canvas.concat(matrix);
canvas.drawText(text, 0, 0, textPaint);
return out;
}
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.
I have a small question. I'm painting some RectFs on my canvas, but nothing happened.
I paint one filled RectF and another stroked RectF => filled background with a border.
For the first "field" everything is ok, but not for the second "field" (rect2).
The positions are checked. The last text is printed in that RectF (rect2) where the rect is not painted.
I uploaded an image on my FTP server. For the description of my problem it might be easier to understand.
Here is my code. I think it is a logical error?
// Fill rect
rect.set(fPosition, fPositionY, pts[2] - 10, fRectHeight);
paint.setColor(Color.GREEN);
paint.setStyle(android.graphics.Paint.Style.FILL);
paint.setStrokeWidth(0);
canvas.drawRoundRect(rect, 10, 10, paint);
// Border
paint.setColor(Color.BLACK);
paint.setStyle(android.graphics.Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawRoundRect(rect, 10, 10, paint);
// Text
float fTextSize = fRectHeight - 40;
TextPaint textPaint = new TextPaint();
textPaint.setColor(Color.BLACK);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(fTextSize);
float textHeight = textPaint.descent() - textPaint.ascent();
float textOffset = (textHeight / 2) - textPaint.descent();
canvas.drawText(dataStrings.getGewicht(), rect.centerX(), rect.centerY() + textOffset, textPaint);
// Leistung pro Stunde
rect2 = new RectF();
paint = new android.graphics.Paint();
fPositionY = fPositionY + fRectHeight + 50;
float fRectWidth = pts[2] / 2;
fRectHeight = (float) (pts[17] / 5);
// Fill rect
rect2.set(fPosition, fPositionY, fRectWidth, fRectHeight);
paint.setColor(Color.YELLOW);
paint.setStyle(android.graphics.Paint.Style.FILL);
paint.setStrokeWidth(0);
canvas.drawRoundRect(rect2, 10, 10, paint);
// Border
paint.setColor(Color.BLACK);
paint.setStyle(android.graphics.Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawRoundRect(rect2, 10, 10, paint);
// Text
fTextSize = fRectHeight - 40;
textPaint = new TextPaint();
textPaint.setColor(Color.BLACK);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(fTextSize);
textHeight = textPaint.descent() - textPaint.ascent();
textOffset = (textHeight / 2) - textPaint.descent();
canvas.drawText(dataStrings.getLeistung(), rect2.centerX(), rect2.centerY() + textOffset, textPaint);
EDIT: The problem came from the emulator, the error did not appear on a real device :(
I'm trying to draw some text in a custom view and must there for measure it but the value of the Paint.getTextBounds() returns a height which is about 30% higher then the actual text which gives everything a quirky look.
I found this: Android Paint: .measureText() vs .getTextBounds() and tried to add the solution code to my own onDraw and saw that i the same measuring error as in my code. Here is a picture of the result:
Compare with:
The image is copied from Android Paint: .measureText() vs .getTextBounds()
Note the spacing above the text in the first picture. Any Ideas what might be causing this? Or are there alternative ways to measure height of a drawn string?
Here is the onDraw method:
#Override
public void onDraw(Canvas canvas){
// canvas.drawColor(color_Z1);
// r.set(0, 0, (int)(width*progress), height);
// paint.setColor(color_Z2);
//// canvas.drawRect(r, paint);
// textPaint.getTextBounds(text, 0, text.length(), r);
// canvas.drawRect(r, paint);
// canvas.drawText(text, 0, r.height(), textPaint);
final String s = "Hello. I'm some text!";
Paint p = new Paint();
Rect bounds = new Rect();
p.setTextSize(60);
p.getTextBounds(s, 0, s.length(), bounds);
float mt = p.measureText(s);
int bw = bounds.width();
Log.i("LCG", String.format(
"measureText %f, getTextBounds %d (%s)",
mt,
bw, bounds.toShortString())
);
bounds.offset(0, -bounds.top);
p.setStyle(Style.STROKE);
canvas.drawColor(0xff000080);
p.setColor(0xffff0000);
canvas.drawRect(bounds, p);
p.setColor(0xff00ff00);
canvas.drawText(s, 0, bounds.bottom, p);
}
i didnot test your code but i dont see any problems with Paint.getTextBounds():
public class TextBoundsTest extends View {
private Paint paint;
private Rect bounds;
public TextBoundsTest(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(32);
bounds = new Rect();
}
#Override
protected void onDraw(Canvas canvas) {
String text = "this is my text";
paint.getTextBounds(text, 0, text.length(), bounds);
Log.d(TAG, "onDraw " + bounds);
int x = (getWidth() - bounds.width()) / 2;
int y = 70;
paint.setColor(0xff008800);
bounds.offset(x, y);
canvas.drawRect(bounds, paint);
paint.setColor(0xffeeeeee);
canvas.drawText(text, x, y, paint);
}
}
add this in Activity.onCreate:
TextBoundsTest view = new TextBoundsTest(this);
setContentView(view);
the result is: