6 things I learned why I was creating an Android App Widget.

Beauty Coder
Beauty Coder
Published in
3 min readAug 28, 2019

--

Widgets are very popular for Android Apps. You can find many of them in the Google Play Store. If you decided to make your own widget app or you planning to add it to your existing app and you never did that before you need to know a few things.

  1. You can use an only predefined list of layouts.
  • FrameLayout
  • LinearLayout
  • RelativeLayout
  • GridLayout

You can not use ConstraintLayouts, you can not use any of your custom layouts even they based on once I mentioned above.

2. You can use only predefined list of Views:

  • AnalogClock
  • TextClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView
  • ViewFlipper
  • ListView
  • GridView
  • StackView
  • AdapterViewFlipper

You can not use any custom class. You can not create a new child class from AnalogClock and use it. It won’t work.

3. To use a custom font, you need to Use Canvas and Paint.

TextViews in Widget doesn’t support custom typefaces. If you want to have a custom font in your widget or you want it to be customizable, you have to draw it into the view.

public Bitmap getTextBitmap(String text) 
{
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
Typeface typeface = Typeface.createFromAsset(this.getAssets(),"typeface.ttf");
paint.setAntiAlias(true);
paint.setSubpixelText(true);
paint.setTypeface(typeface);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTextSize(textSize);
paint.setTextAlign(Align.CENTER);
canvas.drawText(text, x, y, paint);
return bitmap;
}

4. You can not update your widget every minute anymore. If you’re making clock widget without using TextClock or AnalogClock. Or you want to use a custom font you can not do that anymore, and you shouldn’t. You’ll have to use ImageView and update it every 60 seconds, which is not possible. Using AlarmManager or other schedulers won’t guarantee you update every minute. Nowadays Android is much more concern about its battery life.

5. You can not set Vector Drawable inside your layout. Don’t set vector image in layout. Instead set it programatically. views.setImageViewResource(R.id.icon_image_view, icon)

6. Getting widget size is heartbreaking.

In my widget app, I support custom images backgrounds. And not just custom images but also with rounded corners. To implement this you need to get original bitmap and create another bitmap with rounded corners. For that, you need to know the exact height and width. (Image isn’t 9path image). Otherwise your corners can look wrong.

And it’s really hard to get correct width and height, especially if widget id resizable. You can use some AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH and other parameters. But I wasn’t able to get both height and width. On some devices height, I got was wrong. SO I ended up to hard code heigh. So widget was taken smaller space than possible. It works for me. But it still a mess that it’s so hard to get correct width and height. If possible design your widget so it doesn’t depend on the real size of the widget and can easily adapt.

Some useful methods I was using to set up the layout:

I created a widget app that supported alpha, transparency, background images or background color, very customizable and I probably need to rewrite it. But some methods I found useful. Just good to know that they exist.

Set ImageView bitmap: remoteViews.setBitmap(R.id.background_image_view,"setImageBitmap",bitmap);

Set image view resource: remoteViews.setImageViewResource(R.id.background_image_view, res);

Set color filter. In my case, I was using the same imageView to set image background and color. I don’t remember exactly, but for some reasons in my configuration background color didn’t work for me. remoteViews.setInt(R.id.background_image_view, "setColorFilter", color)

If you support customization, you might need to remove it this color filter. remoteViews.setInt(R.id.background_image_view, "setColorFilter", Color.TRANSPARENT);

Set view alpha: remoteViews.setInt(R.id.background_image_view, "setAlpha", 255)

--

--