RemoteViews (Widget) has fuzzy text when using a Bitmap - android

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.

Related

In Android, how can I change a color on a bitmap to another color?

I have a bitmap and want to be able to change all black pixels in that bitmap to blue. I know you can do this via Bitmap.setPixel but that process is extremely slow (believe me, I tried it...even doing the setPixels instead of setPixel).
Researching this is see where people recommend using PorterDuff Xor, but there isn't any posts on how this was successfully done. Lots of people asking...no one spelling out the answer.
So using, paint, bitmap, and canvas, how do you change every black pixel to all blue ones?
Thanks!
you just pull the pixels of the bitmap
myBitmap.getPixels(myPixels, 0 0, 0, 0, myBitmap.getWidth(), myBitmap.getHeight())
and loop over myPixels looking for whatever color you wish and modifying that pixel to whatever color you prefer.

Cutting out the centre region of a Bitmap and shrinking, in Android

I'm trying to dynamically create images in android by taking an existing Bitmap and removing the centre of it in order to make a "cropped" version. The resulting image's height would naturally be smaller than the original, something like the attached example.
I've got a rough way of doing this by creating two new Bitmaps from the original, one containing the top of the image above the crop section (e.g. the android's head in the example) and the other containing the remaining image below the crop section (the android's feet) using the Bitmap.createBitmap(source, x, y, width, height) method, then drawing both of these bitmaps onto a canvas of a size equal to the original image minus the removed space.
This feels a bit clunky, and as I could be calling this method several times a second, it seems wasteful to create two bitmaps each time.
I was wondering if there was a more efficient way of doing this. Something like drawing the original Bitmap onto a canvas using a Path with it's Paint's xfermode set to a
new PorterDuffXfermode(Mode.DST_OUT) in order to cut out the portion of the image I wish to delete. But this seems to clear that area and not shrink the image down i.e. it leaves a big empty gap in the Android's middle.
Any suggestions greatly appreciated!
Why do you create two bitmaps? You only need to create one bitmap and then do canvas.drawBitmap() twice.
Bitmap bmpOriginal;
Bitmap bmpDerived = Bitmap.create(...);
Canvas canvas = new Canvas(bmpDerived);
canvas.drawBitmap(bmpOriginal, rectTopSrc, rectTopDst, null);
canvas.drawBitmap(bmpOriginal, rectBottomSrc, rectBottomDst, null);
Done.

Is there anyway to get the Rect in which Bitmap is drawn on Android?

I am trying to subclass ImageView and draw something on Bitmap. However I cannot find a way to get the Rect in which Bitmap is drawn. I can only get the Rect in which ImageView is drawn by getDrawingRect(Rect) method of ImageView. Below is an illustration of what I want to get:
The Rect I want is the blue one. Thanks in advance.
The given image will be drawn in the ImageView based on the attributes given e.g., height, width, scaling factors, etc.
So that the getDrawingRect() method giving the entire area of ImageView. If you change the drawable inside ImageView the blue colored area may change based on the image properties and imageview properties. But the yellow colored area won't change because it is fixed and based on the ImageView only, its independent of image displayed.
I think no chance to get the Rect of bitmap drawn. Don't think my answer is 100% correct, it is just a suggestion only.
You may get information about blue colored area from Drawing Cache. Try it once.
I hope it may help you.

Can setTextSize() be density independent?

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.

Image/Bitmap placement?

Have any of you seen the simulator bong apps in android? How would you make that app? For example I have tried doing it using xml layouts. I divided the picture up and placed it in order and in segments so that when a particular picture is pressed a function will occur. Problem is that on different phones the size of the collective pictures either extends off the screen or is compressed.
I have also tried using surfaceViews with bitmaps so that each individual picture can take the size of the screen and adjust them accordingly. I am having trouble making the pictures not plop on top of eachother and instead be placed in order going down the screen. I can get the first 2 just fine designating the Rect dst with the starting height being where the other ended but the third and fourth aren't showing up on the screen. For example I used
Rect dst = new Rect(0, 0, mWidth, mHeight/7 );
For the first image which is on the top. Then for the second image
Rect dst = new Rect(0, mHeight/7, mWidth, mHeight/3 );
(mHeight and mWidth is the canvas width and height)
Not sure how to go about placing the next 2 pictures beneath them and eachother. I tried
Rect dst = new Rect(0, mHeight/7+(mHeight/3), mWidth, mHeight/7);
That didn't work though. It honestly looks really simple to do and I'm sure it is, but I just cant seem to get the images to work the way I want. Is there a way to leave the image as a whole and specify when a certain spot is selected it does something (that would work on every phone the same way).
Any help with this would be greatly appreciated. Any other ideas for how to get the result I want are also very much appreciated. Thanks for taking time to read this at all.
Well you could divide the screen into regions like left,top,width,height.
Eg.
Region 1 (0,50,100,100)
Region 2 (100,50,100,100).
And add a OnTouchListener and use that to get touch coords and check which region it belongs to. I'm not sure if it a good way but it is doable.

Categories

Resources