Today Widget Margin Insets

Today widgets in iOS 8's Notification Center have a very clear grid line along the left edge. Most text lines up in a consistent place here. Sometimes a graphic will extend further to the left, but generally there's some text next to it that falls along that same guide line.

There's absolutely no clear way to know where this grid line will fall.

  • On most iPhone sizes, it's about 48 points from the left
  • On an iPad, it's about 57 points from the left
  • On an iPhone 6 Plus in portrait, it's about 52 points from the left
  • On an iPhone 6 Plus in landscape, it's about 81 points from the left

You might be thinking there's an API to get these numbers. You might be thinking that you just have to use the NCWidgetProviding protocol, and get the default margin insets from widgetMarginInsetsForProposedMarginInsets:. That seems like an obvious solution, but it gives a default left margin of 47 points on every device and orientation, which doesn't seem to match up with anything.

Here's a stupid function I made to deal with this mess:

CGFloat JUNTodayViewInset(UITraitCollection *traitCollection) {
	CGFloat inset = 48.0;
	if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
		inset = (traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) ? 57.0 : 81.0;
	} else if (traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) {
		inset = 52.0;
	}
	return inset;
}

Now you're probably thinking that if it's really so important for me to have it line up perfectly, this isn't so bad. The problem is it doesn't actually work, because apparently in a Today widget the size classes are always UIUserInterfaceSizeClassUnspecified. So here's some code that actually works:

CGFloat JUNTodayViewInset(CGFloat width) {
	CGFloat inset = 48.0;
	if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
		inset = 57.0;
	} else if (width > 735.0) {
		inset = 81.0;
	} else if (width > 413.0) {
		inset = 52.0;
	}
	return inset;
}

This is bad code and you should feel bad for using it. I'm using it anyway because it's the only thing that works.

If anyone has a better suggestion I'd love to hear it. I'm guessing most widgets are just using the default insets though—it's probably the more sane thing to do, even if it doesn't look perfect right now.

P.S. I'll file a bug when I have the time! Too busy trying to ship an app right now.

Posted September 23rd, 2014 by Mike Piontek
Link to this entry: https://mikepiontek.com/go/8826

More recent posts