Issue with drawing text on canvas - android

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.

Related

StaticLayout get number of displayed chars like Paint.breakText

I'm using a StaticLayout to draw some multiline text.
StaticLayout is convenient because it handles all the text breaking and new lining for me...
canvas.save();
canvas.clipRect(rect);
canvas.translate(rect.left, rect.top);
staticLayout.draw(canvas);
canvas.restore();
When I just draw a single line I use canvas.drawText() in combination with Paint.breakText to detemine the number of chars I can paint on my available space...
Now I need to know the exact numer of chars that fit in my StaticLayout so that I can paint the rest of the chars to another StaticLayout.
Unfortunaltely I haven't found a method that tells me how many chars fit in it.
Is there something available to get this?
Cheers,
Stefan

StaticLayout height measurements off

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.

Android drawText() in defined rectangular region

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();

How to force the canvas to use only a portion of the area to draw text when extending a TextView

I am creating a custom view that extends the TextView. What I need is a couple of labels on the left handside and another checker on the right hand side of the TextView.
So I can draw those labels and then save the canvas and translate it right so that the text can be drawn beside the bitmaps. This is how I am doing that.
canvas.drawBitmap(bitmap1, 0, top, paint);
canvas.drawBitmap(bitmap2, bitmap1_width, top, paint);
canvas.save();
canvas.translate(bitmap1_width + bitmap2_width, 0);
Here I want to call super.onDraw but ask it to use the width so that the widths of the two bitmaps and the checker are subtracted.
Then I am can call my
canvas.drawBitmap(checker, checkerLeft, top, null);
So after translating the canvas, how can I can tell the canvas in the super.onDraw to use only the measured width? Please feel free to throw in any alternatives. I do want to use canvas though since my requirement is a little more complicated than this example.
Ok I did it by changing the scale factor using canvas.scale(sx, sy) before calling super.onDraw().
This is displaying the text in the way I want. If there is a better answer, please post it.
canvas.save();
canvas.translate(margin, 0);
canvas.scale(scaleX, 1f);
super.onDraw(canvas);
canvas.restore();

Animated Dashed Border in Android

How do you create an animated dashed or dotted border of an arbitrary shape in Android? In XML (preferred) or programmatically.
See picture below for an example.
Have you seen the PathEffects API demo?
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/PathEffects.html
It produces precisely an animated line and you can just adjust the path to the edge of your view to create a border. For example:
Define a path by your view parameters / arbitrary shape:
Path path = new Path();
path.addRect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), Path.Direction.CW);
Then create a dashed PathEffect with:
PathEffect pe = new DashPathEffect(new float[] {10, 5, 5, 5}, phase);
Then set the associate it with a Paint object and draw:
mPaint.setPathEffect(pe);
canvas.drawPath(path, mPaint);
EDIT: The animated effect comes from continuously changing the phase and redrawing. In the API demo it calls invalidate() in the onDraw() method (which triggers onDraw()...)
XML... I guess not possible. But you can use a custom view or a SurfaceView and handle the drawing by yourself. Have fun with that :)
Could you use some form of two 9patch images as a background frame around the image file you want to present, one in each of two layouts. The images would differ in terms of the placement of the dashed elements. Interchange the views rapidly (might need a delay) and you might get the effect you want. Don't really know how effective that would be though in terms of being able to let the user continue using the app and chewing battery...

Categories

Resources