So I'm trying to center a text within it's boundaries. I'm creating a bitmap the size of which is relative to letter String boundaries.
Rect bounds = new Rect();
paint.getTextBounds(s, 0, s.length(), bounds);
Bitmap bitmap = new Bitmap(bounds.width() + 1, (int)(paint.descent() - paint.ascent()), Config.ARGB_8888); //+1 to prevent width = 0, which throws exception
Then I draw the string to that bitmap.
canvas.drawText(s, 1, (i)*paint.descent() - (i+1)*paint.ascent(), paint);
The problem is that with some Typefaces like https://www.fontsquirrel.com/fonts/alex-brush some letters are partially cut off. The bitmap width seems to be alright but letters aren't drawn to the center.
paint.setTextAlign(Align.CENTER);
makes it even worse.
The image below is result of using the code and typeface above with paint's default textAlignment. Drawn String is "j".
Related
i am trying to make an app which can write something on image but the problem is that i dont know how to finish the words or hide overflow of text that user type...if you see in image below you can see that some words go hidden because of no endpoint..i need to make an endpoint in white background
image
this is the part of code that i used
//Rasme mahale bargozari rooye aks
Paint paintMahal = new Paint();
paintMahal.setColor(Color.BLACK);
paintMahal.setAntiAlias(true);
paintMahal.setTypeface(tf);
paintMahal.setTextSize(20);
Rect areaRect = new Rect(0, 0, 300, 100);
Paint rec = new Paint();
rec.setColor(Color.BLACK);
RectF bounds = new RectF(areaRect);
// measure text width
bounds.right = rec.measureText(agahi, 0, agahi.length());
// measure text height
bounds.bottom = rec.descent() - rec.ascent();
bounds.left =57;
bounds.top = 374;
canvas.drawText(agahi, bounds.left, bounds.top - rec.ascent(), rec);
//sakhte akse karbar
Set a clipping region to the canvas. The canvas can only be drawn within the clipping region, anything outside becomes a no-op. Then remove the clipping region when done and draw as normal.
I am currently creating an image editor and am attempting to draw text on top of on image using canvas.drawText(). So far I have been successful in doing this but when the user enters text that is too long, the text just continues on one line out of the page and doesn't wrap itself to the width of the screen. How would I go about doing this? I have tried using a static layout but cannot seem to get it to work, has anyone got a tutorial to do this?
My function for drawing on a canvas using static layout:
public Bitmap createImage(float scr_x,float scr_y,String user_text){
Canvas canvas = new Canvas(image);
scr_x = 100;
scr_y = 100;
final TextPaint tp = new TextPaint(Color.WHITE);
canvas.save();
StaticLayout sl = new StaticLayout("" + user_text, tp, originalBitmap.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
sl.draw(canvas);
return image;
}
Okay, I've updated my code, but when I try to draw on the image nothing happens at all, I have no idea why either:
public Bitmap createImage(String user_text) {
// canvas object with bitmap image as constructor
Canvas canvas = new Canvas(image);
TextPaint tp = new TextPaint();
tp.setColor(Color.RED);
tp.setTextSize(50);
tp.setTextAlign(Align.CENTER);
tp.setAntiAlias(true);
StaticLayout sl = new StaticLayout("" + user_text, tp,
canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
canvas.translate(100, 100);
sl.draw(canvas);
return image;
}
Is staticlayout not meant to be used to draw on canvas?
Yes, StaticLayout is what you're meant to use to draw multi-line text on a Canvas. Save yourself a world of pain and don't think about breaking text yourself -- you're on the right path.
I'm not sure about the bitmap problem, but your second code above worked just fine to draw text on a canvas for me.
Learn to use StaticLayout , then draw the Layout object onto a canvas using the Layout.draw() method.
References
public Bitmap drawMultilineTextToBitmap(Context gContext,
int gResId,
String gText) {
// prepare canvas
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialiased Paint
TextPaint paint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.rgb(61, 61, 61));
// text size in pixels
paint.setTextSize((int) (14 * scale));
// text shadow
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// set text width to canvas width minus 16dp padding
int textWidth = canvas.getWidth() - (int) (16 * scale);
// init StaticLayout for text
StaticLayout textLayout = new StaticLayout(
gText, paint, textWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
// get height of multiline text
int textHeight = textLayout.getHeight();
// get position of text's top left corner
float x = (bitmap.getWidth() - textWidth)/2;
float y = (bitmap.getHeight() - textHeight)/2;
// draw text to the Canvas center
canvas.save();
canvas.translate(x, y);
textLayout.draw(canvas);
canvas.restore();
return bitmap;
}
source : http://www.skoumal.net/en/android-drawing-multiline-text-on-bitmap/
You should handle it yourself, calculating the text size and wrapping the content in some way (break line at max width or wrap last word).
I already did it on Java SE with the FontMetrics, never for Android; but you should take a look:
http://developer.android.com/reference/android/graphics/Paint.FontMetrics.html
As pointed by Lisa, StaticLayout is the way to go to measure text wrapping.
My Desired Output:
Text on the widget(Home Screen Widget) with custom font
My Problems:
Can not use custom font on textview in widget (As TextView's are not directly accessable in widgets, we have to use them using remoteviews.)
So i thought to use imageview and draw text on bitmap using canvas and then set this bitmap on the imageview. So far everything is working but just two thing.
I dont know,
how to make my text to set vertically and horizontally on centre? (Vertically and horizontally means, to be in centre both vertically and horizontally)
how to make my text to fill the entire space of bitmap?
I am using following code to show some text on the widget.
Bitmap bitmap = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.YELLOW);
canvas.drawPaint(paint);
paint.setColor(Color.GREEN);
paint.setStyle(Style.FILL);
canvas.drawText("Test", 50, 50, paint);
and following is the output.
1- Setting font runtime on textview in widget
I dont know that either
2- Setting text to be in center and fill the container
Please see the following code:
float size = 1.0f;
Bitmap bitmap = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.YELLOW);
canvas.drawPaint(paint);
paint.setColor(Color.GREEN);
paint.setStyle(Style.FILL);
Rect rect = new Rect();
paint.getTextBounds("Test", 0, 4, rect);
float width = 1.0f;
while (width<200 && rect.height()<200)
{
size++;
paint.setTextSize(size);
width = paint.measureText("Test");
paint.getTextBounds("Test", 0, 4, rect);
}
size--;
paint.setTextSize(size);
canvas.drawText("Test", 100-width/2, 100+rect.height()/2, paint);
I was trying to attach the screen shot but it wont allow me to add as i am a new user.(rookie :P)
Thanks,
Hello Why you can't use a custom font on TextView: i think you can just subclass TextView and add this the three default text view constructor
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/ds_digib.ttf");
setTypeface(tf);
}
To make your text set vertically and horizontally
see this link
hope this will help you to resolve your problem
Can not use custom font on textview in widget
TextView tv=(TextView)findViewById(R.id.custom);
Typeface face=Typeface.createFromAsset(getAssets(),"fonts/Verdana.ttf");
tv.setTypeface(face);
if you want to use same in canvas then set the face to paint obj which u r using.
how to make my text to set vertically and horizontally on centre?
In canvas as your drawing text by paint obj. then you can set paint obj
mPaint.setTextAlign(Align.CENTER);
or you can place to left or right. You can't set vertically or horizontally because ur drawing the text so you draw as you want vertically or horizontally.
example you need to draw text SAM
horizontally means canvas.drawText("SAM", 50, 50, paint);
veritically means
canvas.drawText("S", 50, 50, paint);
canvas.drawText("A", 50, 51, paint);
canvas.drawText("M", 50, 52, paint);
NOTE : then you might think what is mPaint.setTextAlign(Align.CENTER), right or left. so example if you ve 100 widht and you start writing from 20px to 50px means then its tries to keep in center from 20 to 50 px. NOT in center to widht 100px.
how to make my text to fill the entire space of bitmap?
You will not find any wrap content here because in Canvas we have to our self.
so first check how much space u have and fill the give x and y values and also change the text-size prepositionally .
I'm using a Canvas to create a Drawable with some background and some text. The drawable is used as a compound drawable inside an EditText.
The text is drawn via drawText() on the canvas, but I do have an issue with the y-position of the drawn text in some cases. In those cases parts of some characters are cut off (see image links).
Characters without positioning issue:
http://i50.tinypic.com/zkpu1l.jpg
Characters with positioning issue, text contains 'g', 'j', 'q', etc.:
http://i45.tinypic.com/vrqxja.jpg
You can find a code snippet to reproduce the issue below.
Does any expert know how to determine the proper offset for the y position?
public void writeTestBitmap(String text, String fileName) {
// font size
float fontSize = new EditText(this.getContext()).getTextSize();
fontSize+=fontSize*0.2f;
// paint to write text with
Paint paint = new Paint();
paint.setStyle(Style.FILL);
paint.setColor(Color.DKGRAY);
paint.setAntiAlias(true);
paint.setTypeface(Typeface.SERIF);
paint.setTextSize((int)fontSize);
// min. rect of text
Rect textBounds = new Rect();
paint.getTextBounds(text, 0, text.length(), textBounds);
// create bitmap for text
Bitmap bm = Bitmap.createBitmap(textBounds.width(), textBounds.height(), Bitmap.Config.ARGB_8888);
// canvas
Canvas canvas = new Canvas(bm);
canvas.drawARGB(255, 0, 255, 0);// for visualization
// y = ?
canvas.drawText(text, 0, textBounds.height(), paint);
try {
FileOutputStream out = new FileOutputStream(fileName);
bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
} catch (Exception e) {
e.printStackTrace();
}
}
I think it's probably a mistake to assume that textBounds.bottom = 0. For those descending characters, the bottom parts of those characters are probably below 0 (which means textBounds.bottom > 0). You probably want something like:
canvas.drawText(text, 0, textBounds.top, paint); //instead of textBounds.height()
If your textBounds is from +5 to -5, and you draw text at y=height (10), then you'll only see the top half of the text.
I believe that if you want to draw text near the upper left corner you should do this:
canvas.drawText(text, -textBounds.left, -textBounds.top, paint);
And you can move around the text by summing the desired amount of displacement to the two coordinates:
canvas.drawText(text, -textBounds.left + yourX, -textBounds.top + yourY, paint);
The reason why this works (at least for me) is that getTextBounds() tells you where drawText() would draw the text in the event that x=0 and y=0. So you have to counteract this behavior by subtracting the displacement (textBounds.left and textBounds.top) introduced by the way text is handled in Android.
In this answer I elaborate a little more on this topic.
Can someone explain what the rect does in: canvas.drawBitmap(bmp,scr ,dst ,null);
Because I have tried and tried to make any sense of this but I simply don't understand what the two rectangles does.
My goal is to display a portion the bitmap instead of the whole image.
//Simon
Rect src = new Rect(0, 0, 50, 50);
Rect dst = new Rect(50, 50, 200, 200);
canvas.drawBitmap(originalBitmap, src, dst, null);
This code specifies that you want to copy a rectangle with the dimensions 50 width / 50 height of the source starting at position 0x 0y, and draw into the destination bitmap starting at position 50x / 50y and occupy it until 200x 200y - therefore stretching a bit - because as the source is only 50 pixels long, to stretch to 200x and 200y the copy will end up with the size 150width / 150 height.
The Android documentation seems to explain this method quite well.
drawBitmap Documenation
From reading the documentation it appears you can do what you want by specifying a source Rect, which will be the rectangle(subset) from the original bitmap, and it will then be translated into the dest Rectangle.
Bitmap picture; //Assume this is a 1024x768 image and has been initialized.
#Override
public void onDraw(Canvas canvas){
//To Draw only the top left corner of the image
Rect src = new Rect(0,0,512,368);
Rect dest = new Rect(0,0,512,368);
canvas.drawBitmap(picture, src, dest, null);
}