I have an app that contains a custom view, and in it I want to use a custom font. Unfortunately, this results in really ugly text being rendered.
My custom view extends Surface (and just realized: is this a bad idea), and I draw the text with the following code:
// p = new Paint();
Typeface font = Typeface.createFromAsset(parent.getAssets(), "komtit.ttf");
p.setColor(Color.BLACK);
p.setTypeface(font);
c.drawText(this.text, x + width / 2 - p.measureText(this.text) / 2, y + height / 2, p);
The result looks like this:
http://img.skitch.com/20101014-rxw8j8igj1jci2fx9ui32ejcp.jpg
Not fun. I'm using p.setFlags(Paint.ANTI_ALIAS_FLAG) but even with that the result is just fudgly.
So, is there a way to improve custom TTF rendering, or should I just stick to the system fonts?
Answering my own question here. The problem was that I was extending Surface (which I really in the end didn't have a proper reason for) which apparently uses OpenGL for rendering and OpenGL and custom TTF fonts don't mix.
When I switched to extending just View, the font looks perfect.
Related
To place a custom font on my widget I am creating a bitmap with the font inside of it, and then placing that bitmap into my RemoteViews. However the text on the bitmap is pretty fuzzy, and looks really pixelated compared to how crystal clear it is within an Activity.
There are quite a few apps already that use custom fonts on a widget. I haven't found a solid way to do this yet though. If anyone has a better solution to this problem I would love to hear it!
Right now this is what I am using to create the bitmap and place it on the widget:
RemoteViews widgetView = new RemoteViews(this.getPackageName(), R.layout.widget);
widgetView.setImageViewBitmap(R.id.widgetImage, buildBitmap());
with
public Bitmap buildBitmap() {
Bitmap bitmap = Bitmap.createBitmap(160, 84, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
TextPaint textPaint = new TextPaint(TextPaint.LINEAR_TEXT_FLAG | TextPaint.ANTI_ALIAS_FLAG);
textPaint.setTypeface(getFont());
textPaint.setStyle(Style.FILL);
textPaint.setColor(fontColor);
textPaint.setTextSize(fontSize);
StaticLayout staticLayout = new StaticLayout(textString, textPaint, bitmap.getWidth(), Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
staticLayout.draw(canvas);
return bitmap;
}
The culprit Widgets! The one on the top is with the custom font, the middle image is with the default Sans font on a bitmap, to show that the text is fuzzy no matter what font is used.
The Last image is what the text looks like when using the default remoteView.setTextViewText("Text"); instead of a bitmap.
Any assistance on this problem would be greatly appreciated!
You can't assume 160x84. That's a very small size. When scaled it will likely be fuzzy as you can see. Instead, you'll want to actually measure out the bitmap size based on measurements of your text at a given sp. Paint.measureText is useful sometimes for these kinds of things to get the width, but you'll need height as well to do it right, so getTextBounds might be more useful. You'll probably need to add some padding too, but this should get you started. As you can see in your pictures, the clarity is not the only problem you have to deal with. You'll have to figure out word wrapping too (perhaps here is where Paint.measureText will come in handy).
The ImageView you are using requires android:scaleType="matrix" attribute to be added. Edit your widget layout xml and add that attribute where needed. The ImageView will then not try and scale your image to fit the view.
As previous posts have said your pixel dimensions are wrong. You should be maintaining a record of the size of each of your widgets so you can later use it for creating the bitmap.
If you want help working this bit out I can post some code. Accept this answer and post another about that question specifically and I will answer there with the code.
I'm writing a custom View for a timer, but I can't get a properly fixed-width font for the numbers in the middle. Here's the relevant code (from two different methods):
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL));
// Get rectangle that is the size of the text
mTextPaint.getTextBounds(
getTimeText(),
0,
getTimeText().length(),
mTextBounds);
// X and Y coordinates of text
float mTextPosX = (width / 2) - (mTextBounds.width() / 2);
float mTextPosY = (height / 2) + (mTextBounds.height() / 2);
// Draw text
canvas.drawText(
getTimeText(),
mTextPosX,
mTextPosY,
mTextPaint);
This seems to work fine, but whenever one of the numbers changes to a 1, that 1 takes up less space and the whole chunk of text moves over a bit. This obviously should not be happening, since I'm using a monospace font. Can anyone shed some light on how I might fix this?
I had the same problem. A way to fix it is by using an external font in which "1" behaves as expected. A website with many fonts to try is this one: http://www.fontcubes.com/ . A related discussion on how to use external fonts in Android is here: How to change fontFamily of TextView in Android .
I'm looking into methods of completely blurring a text in a textview. Read, completely unreadable (pixelate). The methods i'm using now are using shadows. But this seems very inefficient. Anyone who has a better solution?
I did not like the Paint method used in the other answers. The below code is working for me with the radius calculated depending on the font size and applying it directly on the TextView.
if (Build.VERSION.SDK_INT >= 11) {
yourTextView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
float radius = yourTextView.getTextSize() / 3;
BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL);
yourTextView.getPaint().setMaskFilter(filter);
You should try to use canvas instead of TextView and draw a text with blur.
There is a lot of method using BlurMaskFilter and you can use this like that :
paint.setMaskFilter(new BlurMaskFilter(float radius, BlurMaskFilter.Blur style));
You may try below methods:
Whenever you want to show blurry text, use a specialized font for
your TextView, added to asset folder of your project.
Try setting a transparent color[#00ffffff] to your text and give some shadow to it.
I hope one of the above method helps.
If you are looking to obfuscate the text you can try using TransformationMethod of TextView.
Here you have an example, is not a blurring effect but may help: https://gist.github.com/RicardAparicio/bdd6cd30410f9431e1da238202a1dfa9
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);
}
If I were to initialize a Paint, and set it's text size like so:
Paint = new Paint();
Paint.setAntiAlias(true);
Paint.setARGB(255, 255, 0, 0);
Paint.setTextSize(screenWidth/100);
//screenWidth is the width of the screen in pixels given via display metrics.
And then draw text to the canvas like so:
String text = "Hello"
canvas.drawText(text, (screenWidth/13), (screenHeight/5), Paint);
Would the text Show up in the same relative spot the same relative size regardless of screen metrics? I ask because I only have 1 device and the Emulator doesn't run very well on my multi-core machine.
What I've been doing up until this point is simply using a bitmap with the text written over a background, but my memory usage is getting quite heavy, so I'm looking to cut down on the number of bitmaps loaded.
My other option is to save the text as a bitmap with a transparent background and overlay it on a single bitmap background. But that seems to be only half as productive, as it is actually creating 1 more bitmap, just reducing the total size of all the bitmaps stored. I also don't like this idea because i'd eventually like to take more control over the object life cycle and this will make that less effective.
Also, is there any method of adding styles to text (such as complicated fonts and color patterns besides using pre-made Drawables) so that the text can be drawn to canvas? (As cheaply as possible)
NVM, Solved By Poking around all day I figured out that DP units can be called from the res folder and will give a fairly uniform position of the text. and that paint is not as customization friendly as I wish.