widget margins

Quick guide to the new app widget padding/margins in ICS / Android 4.0+ (backwards-compatibility & new issues)

For those who don’t know, Mike & I make a popular widget app for Android called HD Widgets. We’ve spent a lot of time resolving for Android UI fragmentation and have been mostly successful.

Recently we made the jump to the latest Android sdk (15). We did this to take advantage of the new features and give HD Widgets a long runway. Unfortunately, the “creative” folk behind Android decided to throw a new curve-ball that started with sdk 14: forced widget margins:

Note: As of Android 4.0, app widgets are automatically given margins between the widget frame and the app widget’s bounding box to provide better alignment with other widgets and icons on the user’s home screen. To take advantage of this strongly recommended behavior, set your application’s targetSdkVersion to 14 or greater.

While they say “strongly recommended”, it’s actually a forced feature. This is a setting you have no control over – it’s automatically added and you can’t change it.

What does this mean? It may seem like a small change but it will have a dramatic effect on your layouts. Essentially if you build using the ICS APIs, widgets are reduced in size by ~15% on ICS devices and *only ICS devices* ! While this was implemented solely to make Google’s Launcher look better, it affects all launchers on the device.

Here’s what you’ll see if you use the new sdk and use the built-in margins:

 

Backwards-Compatible Padding

The best solution for backwards size-compatibility is to use @dimen to assign dynamic padding depending on OS version. So each of our widgets has this as our base layout:

From here we create two dimens.xml files, one for your values folder, and the other for values-v14:

values/dimens.xml

values-14/dimens.xml

The key here is that all devices get an extra 6dp of padding, but we revert that to 0dp for v14 devices so they only get the native padding.

Final Tip: remember that the xml value is singular: dimen but the file name is plural: dimens.

New Issues (the size war)

While this solution works great for backwards-compatibility there’s a many upcoming issues that you’ll need to be aware of which are unique to ICS devices.

The most critical issue is that widget sizes are going to vary greatly between manufacturers. Samsung wants full screen-width sizing, HTC wants large but with a little padding, and Asus & Motorola seem to want to keep the tiny Nexus-like sizing.

The size inconsistency trickles down to third party launchers and ROMs. For example here’s the grid size difference between the native launcher and ADWLauncher EX on the Galaxy Nexus:

Similar to Honeycomb, the new ICS launcher’s grid isn’t actually full screen. The native ICS launcher features a non-removable Google Search Bar on the top. To keep the grid layout proportional, they reduce the total grid size by 20%. That causes another dramatic size difference between layouts of launchers even on the same device.

There’s also a major bug introduced in ICS 4.0.3 (at least for tablets) whereby widgets are given the same height as app icons. Until this release widgets we as high as the icon plus text. This bug reduces the height of ICS tablet widgets to 72 pix from 90 pix – basically 25% shorter (along with the extra padding).

The last issue introduced by ICS’s new widget margins is that sometimes the native launcher hiccups and forgets to auto-apply the margins, resulting in unsightly bloated widgets:

I’ve seen this pop up a few times. I don’t know why & I haven’t found a pattern. Needless to say, you may get feedback from your users about this so it’s useful to know it happens.

[Update 4/24/12: changed the code from using multiple RemoteViews to using @dimen padding. The RemoteViews method seemed to work fine and offered more flexibility, but @dimen is part of the Developer Documentation so it is less likely to break in the future.]

[Update 6/12: after launching HD Widgets 3.0 we discovered that some manufacturers ignore the setting, as well as the 4.0.3 shrunken widget bug. Updated accordingly.]

Comments (15)

  1. The method does not seem to work on many stock launchers?

    I tested on:
    Asus TF700 4.0.3: padding enforced no matter what
    Iconia A500 4.0.3: padding also enforced
    Galaxy Tab 2 4.0.3: no padding ;)
    Galaxy S3 4.1.1 + Nova Launcher: no padding ;)
    Galaxy Nexus 4.1.1 + Nova Launcher: no padding ;)

    I added the dimens, the FrameLayout with a reference to that, added v14 versions of all widget info XMLs (for min sizes dp), but no luck!

    Am I missing something???

    No other solution but to stick with target SDK 13… But what then if I need SDK 15?!

    • The technique is only for bringing older devices into line with Google’s extra padding. There’s no way I know of to distinguish between different ICS/JB devices.

      Eventually you’re going to need sdk14 or later. I posted this as a warning so everyone would know what to expect.

  2. I have to questions for you if you would be so kin
    1: Do I undertsand this correctly if I’m left with the impression that there is NOTHING any widget devs can do about it – Your widgets WILL have padding on ICS no matter what?
    2: Is there something launcher devs can do? I have tried apex, nova and Adw EX, bot no margin settings in the launchers fixes this. If (the otherwise crappy) TouchWiz launcher can simply choose to ignore those margins, maybe there is hope. I have no use what so ever for 40% wasted screen real estate and miniature widgets.

    • It’s actually a little worse than that: only certain devices enforce the padding. Aside from the Galaxy Nexus, Samsung disregards (i.e. removes) the padding. Same with HTC. But Motorola & Asus still use it… Turned our launch into quite the mess.

    • For my widgets, after testing with quite a bunch of launchers and devices, the “solution” has been not to compile against ICS SDK, but use the android 3.2 SDK (v13). This way no padding is enforced at all and it all seems to work as intended in every device.

      I think google should think a lot about this kind of decisions that ends up being a nuisance to developers, instead of making it all easier for us. But well, after all they are the ones that decided to implement an OS in crappy slow java to be run in devices with very limited memory and power, make the whole UI system a single threaded piece of $%&#, and disabled real multithreading in AsyncTasks in honeycomb “because people abused it” so its not a surprise to me anyway :(

      And I dont forget their biggest achievement in OS development, optional API functionality. Every time I read in the docs “this flag/method/parameter may not have any effect, or not be implemented at all, so you can use it but sometimes it will work and sometimes it wont, but you cant query about it anyway”. Say what?

      Oh, and BitmapFactory is the biggest piece of pure evil implemented in any system I ever developed on.

      Wise up google!! Even the crappy extinct windows 95 with 1/4 the memory and CPU power of any of current low end device can give android a run for its money.

      Oh mama….

  3. In fact there is another problem. The automatic padding from the ICS system shows up only with the default ICS launcher, but in SGS II with ICS and the embedded Samsung’s TouchWiz, the crappy Gingerbread-like launcher doesnt add any padding, so when you start the widget, the padding is taken from the values-v14 folder (its an ICS device indeed) but TouchWiz doesnt add any padding, so the end result is that the widget doesnt get any padding from anybody.

    If you use another launcher, like the ICS only Apex Launcher (a really nice launcher, I think) the widget does get padded by the launcher, but only if the widget is built with v14/v15 target. If the widget is built for v10 (i.e.) it doesnt get padded either, but as the values are taken from values-v14 there is no padding from there either.

    This is the kind of things that drives me crazy about developing for android :(

    • From what I’ve heard the idea was that we should let the launcher determine the size & layout. Unfortunately, Google & Samsung have extremely opposite design goals for widgets: Google wants thick gaps between and heavy padding resulting in very squished widgets, while Samsung is designing for full-screen sizes. Meanwhile, HTC is doing extra-large screens…

      At this point I’m thinking I may need unique layouts just for the Galaxy Nexus since its gaps/spacing are so out of sync with everyone else and it’s easy to target a single device.

  4. I am a dveloper and I have developed a widget build against API 8, TargetSDK 8. Everything nice and fine so far. Recently I updated my SGS to ICS 4.03 and took the chance to test against ICS on a real device. As I am in the process of moving all my apps to ICS, I build against API 15 and with TargetSDK set to 15.
    Now what happens, is that the widgets disappear from the new app/widget launcher???

    If I build against API 8 with TargetSDK set to API 8, it will appear like all pre-ICS widgets in the launcher (with the thin frame around them) like expected…

    In Eclipse I can see that 5 new parameters have been added:
    PreviewImage, Auto advance view id, Resize mode, Min resize width, Min resize height.
    I assume, to make the widget appear in the launcher, I have to specify some of these values?

    BTW, I am using HD Widgets on my SGS and on my Acer Iconia tab since you published the first version, I am completely happy. No other clock/weather widget around which looks as good and is as configurable than your HD Widgets :) (And I tried all major clock/weather widgets). I especially love the transparent version which blends in so nicely, on whatver wallpaper is in use. Great work!

  5. Thanks dude, really useful.

    One weird thing I noticed though, is that ICS margin measure appears only once : when you first set the widget.

    Which means : if you update your widget, and that the previous version was compiled for android 10, and that you the next version is compiled for android 15, the margin are not re-measured on update, and your previous version will still have the old-style margin (ie : no margin at all).

    Did you find a solution for this particular issue ?

    Thanks in advance.

    • No idea. I’d save that kind of change for a major update and tell users they need to reinstall the widget. I’d probably include a nice carrot to make it feel worth their while…

      • Can’t do that, it’s a note widget ^^ (memento)
        Well, I guess it’s not that important, only a few users will be impacted, and they might create new widgets on their own if they want.

        I wanted the neat widget resize capability that comes with Honeycomb and ICS ! But only ICS adds the “minResizeWidth” and “minResizeHeight” params, so… I compiled against Android 15.

        Anyway, thanks for the tip, I kind of feel bad I didn’t thought about it on my own.

        • It sounds like they’re sticky notes so they’re disposable. Old ones will be over-padded and will inevitably be replaced by normal ones. Don’t think you’ll get much complaints (particularly if you point out how/why it happens).

          Of course there’s an opportunity here to add a carrot or two: back-up & reload notes, send via email, notification alarm…

Leave a Comment

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">