I'm currently using the following method to draw some text to the SurfaceView:
canvas.drawText("someText", 0, 0, paint);
Yet what if the text exceeds the width of the screen? Is it possible to define a region wherein the text can be drawn?
So now when the string's width exceeds the rectangles width, the text will be formatted to fit underneath the above text and so on eg.
"sometext"
"text carried"
"on"
Based on this answer, I believe this is what the Layout subclasses are used for. Per documentation:
A base class that manages text layout in visual elements on the
screen.
For text that will be edited, use a DynamicLayout, which will be
updated as the text changes. For text that will not change, use a
StaticLayout.
And with each subclass there's a note:
This is used by widgets to control text layout. You should not need to use this class directly unless you are implementing your own widget or custom display object, or would be tempted to call Canvas.drawText() directly.
Which sounds exactly like what you're doing.
It's basically a replacement for canvas.drawText(). It can be used in this fashion:
TextPaint tPaint = new TextPaint(paint);
StaticLayout sLayout = new StaticLayout(sText, tPaint, mWidth, widthToFill, Layout.Alignment.ALIGN_CENTER, 1.2f, 1.0f, false);
canvas.save();
canvas.translate(posX, posY);
sLayout.draw(canvas);
canvas.restore();
Related
I have a canvas on which I have drawn some text using drawText(), is it possible to get a reference to that text? I want to select that text using the onLongPress() gesture and I think I need to have the reference of that text to do that.
You won't be having refrence to what you drawn using drawText() on canvas.To implement select text you have to use Paint.measureText() to get height and width of your text and then draw the backgound to make a custom effect of text selection(handle long press using onTouch()).
When drawing text on canvas you have to handle every behaviours of text view as your own.
An alternate way is to to Create a TextView and add it to any layout and then use the following code to draw the layout into canvas
//measure the width and height of the layout(covers entire canvas)
vLayout.measure(canvas.getWidth(), canvas.getHeight());
//set the bounds of the layout.
vLayout.layout(0, 0, canvas.getWidth(), canvas.getHeight());
vLayout.draw(canvas);
I am trying to draw multiline text to a bitmap with the font Latto-Reg, and StaticLayout seems to have problems with it.
paint.setTextSize(label.fontSize);
paint.setTypeface(face);
StaticLayout textLayout = new StaticLayout(label.text, paint, (int)StaticLayout.getDesiredWidth(label.text, paint), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
Bitmap bitmapAux = Bitmap.createBitmap(textLayout.getEllipsizedWidth(), textLayout.getHeight(), Bitmap.Config.ALPHA_8);
canvas.setBitmap(bitmapAux);
canvas.save();
canvas.translate(0, textLayout.height());
textLayout.draw(canvas);
canvas.restore();
The texture has padding on top and bottom depending on the font and size, while the text fits perfectly in the bitmap it is a lot of wasted memory space and makes laying it out to be off by a random amount.
I tested using single-line drawing and the bitmap was perfectly fitting the text
paint.getTextBounds(label.text, 0, label.text.length(), rect);
Bitmap bitmapAux = Bitmap.createBitmap(rect.width(), rect.height(), Bitmap.Config.ALPHA_8);
canvas.drawText(label.text, -rect.left, -rect.bottom, paint);
I have tried getting all kinds of metrics from StaticLayout and all of them seem to be off from the text: line 0 bounds, line 0 top, last line bottom...leading to the same padding problems.
EDIT:
I solved the problem by using offset-based single line drawing. Still the StaticLayout class was drawing incorrectly with several different non-standard fonts and I want to know why.
Looking at the android developper page, it looks like it's designed to handle both the multi-line case and being used next to another Layout well, and hence there is space on top of the line of text so that if you place it directly below another Layout it will be correctly spaced. In essence, it's just not designed for what you are trying to achieve.
Overall, it may be easier to get the Text bounds from Paint.getTextBounds() to know what the extent of the text will be within the Layout.
I've created a minimal working example of what I think you're trying to accomplish: creating a bitmap precisely large enough to contain the text rendered through a StaticLayout.
It seems that there are a few things wrong with your code:
You're needlessly translating vertically inside the bitmap;
There doesn't appear to be a height() method for StaticLayout.
Here's my result:
I added a green background to illustrate the size of the bitmap, but otherwise, my code differs very little from yours:
public void createTexture() {
int width = textLayout.getEllipsizedWidth();
int height = textLayout.getHeight();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas2 = new Canvas(bitmap);
Paint p2 = new Paint();
p2.setStyle(Style.FILL);
p2.setColor(Color.GREEN);
canvas2.drawRect(0, 0, width, height, p2);
textLayout.draw(canvas2);
}
I created a very simple custom component to draw the bitmap:
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, paint);
}
It seems that perhaps you're translating to draw multiple textures after one another. I'd recommend that you do so in your draw method instead, translating vertically in the height of the previous texture after drawing it.
I would like to know if it is possible to add a textview programmatically in a custom view that herites from View. In this customView, I draw some shapes with a canvas and I need to put some text too. I tried to use drawText but it doesn't offer enough possiblities, especially for the position of the text. Basically, i want to put text inside, and precisely in the middle of a circle and at the same time that my text fits right in the circle (I already know how to do that).
That's why I'm wondering if it is possible to add a textview by just declaring it and draw it. Maybe I need to use an Inflater ?
I don't really know what are the best choices so I need your help :)
You can use drawText(String text, float x, float y, Paint paint) method for this.
Like this :
Paint mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText("YOUR TEXT HERE", 10, 20, mPaint);
Instead of extending View you should extend a ViewGroup subclass like
FrameLayout.
This way you can still use the canvas to draw your custom view, but also add children views to your custom drawn viewgroup.
I am working on a custom View that includes frequently updated text that I want to anchor to the bottom of the canvas.
The text length changes as well, and I'd like it to wrap, moving up the screen as more lines are needed. (DynamicLayout thus seems like a solid choice for automating this)
However, I don't see any options in the docs about specifying where on my canvas the text is drawn or in which direction it should "grow".
Here is my initialization:
TextPaint subtleTextPaint = new TextPaint();
DynamicLayout dl = new DynamicLayout(text,subtleTextPaint,getWidth()
,Layout.Alignment.ALIGN_CENTER,1,0,true);
And in onDraw(), I simply pass the canvas to the DynamicLayout object like so:
dl.draw(c);
Right now, the text is drawn at the very top of the screen and word-wraps downwards as the text gets longer.
After quite a bit of searching, I found nothing that did what I wanted. So, in true hacker style, I created my own solution. By extending the DynamicLayout class and overwriting the getLineTop() function, I was able to achieve the functionality I was looking for.
I've posted the source code here.
What i think 1st you get the Width of the screen and then set the Text with the X y according to your screen dimension
that will work
snippet is following
width=canvas.getWidth();
if(width==720)
{
canvas.drawText(String, x , y, drawText);
}
else if(width==480)
{
canvas.drawText(String, x , (y, drawText);
}
else
{
canvas.drawText(String, x , (y, drawText);
}
i am drawing text on canvas using drawText() method.But when line is bigger then screen it is cutting text means if line is greater than screen size then it should come to new line,but it is not happening.Any help will be appreciated.
What you are looking for is StaticLayout.
You can use Android.text.StaticLayout class and call it's draw(Canvas) to draw text which wraps onto the next line.
The Canvas.drawText methods do not automatically handle line-wrapping. You will have to do this yourself. You could try using the breakText methods in the Paint object—not sure if these break on word boundaries, or simply on whole characters.
Try:
mTextLayout = new DynamicLayout([charseq], paint, width,
Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
This will layout your text limited to a specific width.