Android Canvas drawText with SpannableString - android

I made a custom View using Canvas.drawText() to draw some SpannableStrings.
I call SpannableString.setSpan() when the text contains emoji I made(I don't like the default-style emoji).
I found the Canvas.drawText() does not draw the span I set and instead, it draws the default-style emoji.
I tried to call TextView.setText() passing the same SpannableString and it works.
I want to use Canvas to draw the text for performance(Otherwise, newing several TextViews while scrolling in ListView causes severe problem about performance). How can I draw SpannableString with Canvas?
Sorry for my poor English, I am not a native speaker. Thanks for advance!
EDIT: Actually I made this custom View in order to show animation of text transitions. Several texts will go across the screen horizontally. The problem I met is that the TextView's draw method causes too much time and the animation looks bad. So I want to draw the text directly using Canvas. Sadly, I switched to StaticLayout and still found the animation is jerky.

You could try adding your Spannable to a StaticLayout and draw that to a Canvas.
Something like this:
StaticLayout layout = new StaticLayout(yourSpannable, yourPaint,
yourCanvas.getWidth(), Alignment.ALIGN_NORMAL, 1, 0, false);
layout.draw(yourCanvas);

Related

How to draw over small portions of custom view?

I'm using a custom View to draw rectangles(which will have text inside them at a certain point) and I want to highlight each rectangle when selected, which will happen every few seconds when user selects a rectangle. Should I implement highlighted rectangle in onDraw or is there a way just to redraw each rectangle without redrawing the whole View? I was thinking of using "invalidate(rect)" but it's been deprecated.
I'm trying to be considerate of the cost of invalidating the whole View compared to just redrawing a rectangle.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(CellCoordinates cellCoordinate : mCoordinateCells) {
canvas.drawText(" ", cellCoordinate.getRect().exactCenterX(), cellCoordinate.getRect().exactCenterY(), cellPaint);
}
}
Using invalidate() and onDraw() is fine. Dirty rect is not really have effect on API21+
... In API 21 the given rectangle is ignored entirely in favor of an internally-calculated area instead. ...
Dirty rect is deprecated because of different drawing model in hardware accelerated views. Checkout this link for more information
Also, it seems your rectangles can be implemented as custom Drawables with states (selected and normal). It will not give you extra performance, but might help to divide and structure code for drawing. This might help

Auto set rectangle length on canvas as per string length

I have an array of strings and I have drawn those strings on screen using android graphics library (Canvas, Paint). Firstly, a transparent rectangle is drawn then on this rectangle I paint the strings, giving the impression of text with border line and filled.
The problem is some strings are long and some are short, how can I modify the rectangle so that it is as long and as wide as the string is? (Like WRAP_CONTENT in textView)
Currently I am using this method
canvas.drawRect(_x-10, _y-10, _x+620, _y+30, rectanglePaint);
canvas.drawText(placeName, _x, _y, textPaint); //text
If there is a better way then please do let me know.
Note: It will be used in an AR app so the text will be moving from left to right and vice versa as the mobile is moving. _x, _y for place name works perfectly in 2nd line, I want text should remain highlighted, no matter how the mobile is moving.
Paint has a measure text method that will give the width of the text if it were to be drawn with that paint. Its get font metrics will probably give you some data that you can calculate the height from. The sizing, positioning, wrapping and rendering of text is a very complicated problem and I would advise using a child TextView (with a background) in your ViewGroup rather than trying to roll your own if you're doing anything complicated.

change canvas size for TextView

I need use TextView with outline text. I try use it: https://stackoverflow.com/a/10294290/4181010 , but it doesn't work correctly with android:layout_width="wrap_content", because it doesn't increase canvas when add outlines.
I need to increase the canvas to include the value of strokeWidth.
I suggest I have to override onMeasure somehow, but TextView call final method setMeasuredDimension at the end of onMeasure to apply view size and I can not intervene at this point so as not to have to rewrite the whole method.
Scaling the canvas in OnDraw does not work either, because TextView scales draw text with canvas.
My solution is increase canvas and use canvas.translate() to move in right position before draw text.
And my question: How can I increase the size of the canvas with minimal intervention? Or someone know another solution for this problem?
I'm guessing you are drawing the text twice, once with the orange (manually on the canvas) and once with the white (what the TextView is drawing with super.onDraw).
Instead of drawing the larger orange manually, you could instead draw the smaller white text and leave the orange text to TextView's super.onDraw. That way everything should fit within the canvas.

Issue with drawing text on canvas

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.

Custom class ImageView written text ends up behind setImageBitmap

hi
The custom ImageView is setting a Bitmap like this, in the constructor.
setImageBitmap(btm);
In my onDraw method im writing text like
canvas.drawText
Text is showed and I can move the text around using onTouchEvent.
But the text is behind the Bitmap.
I thought setImageBitmap(btm) would be part of the Canvas??
Any ide!
When i draw the Bitmap in onDraw like this, The screen is black!!
canvas.drawBitmap(bitmap, 0,0, null);
If you want an ImageView that also displays text and you're already handling onDraw, why not just draw the Bitmap manually to the Canvas in onDraw? That way you have control over the order of the drawing. Draw the image to the canvas first and then the text, and the text will no longer be obscured by the image.

Categories

Resources