38

How can i change the height of my App's Today Extension in the Notification Center?

I tried it with the Interface Builder and with Code, the Interface Builder Displays the View with height 600, but it's not applying this height on the device.

It seems I can't get it bigger than some 80 pixels...

enter image description here

Gotschi
  • 3,175
  • 2
  • 24
  • 22

6 Answers6

76

In your widget UIViewController.m (Objective-C):

self.preferredContentSize = CGSizeMake(0, 200);

Will make your widget have a height of 200.

Note that the width will have no affect on the view, as widgets must fit in the exact width of notification center, which is handled automagically.

Also, if you want to animate changes in the height of your view, you can implement (Objective-C):

- (void)viewWillTransitionToSize:(CGSize)size
       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

in your view controller using -animateAlongsideTransition:completion:

The answer was a bit hidden; you had to click around in the documentation sidebar to eventually find this fantastic document.


Another way is to use auto-layout constraints to constrain your view's height.

Pang
  • 9,564
  • 146
  • 81
  • 122
Andrew
  • 15,357
  • 6
  • 66
  • 101
  • 2
    This is not the recommended method. As stated in the sessions, you should use auto layout. – Isaiah Turner Jun 04 '14 at 18:55
  • @IsaiahTurner Thanks. I haven't gotten a chance to watch yesterdays sessions online yet... – Andrew Jun 04 '14 at 18:58
  • preferredContentSize does not work well in landscape mode. Looks like there is no enough room for the widget. @SantaClaus Could you please share some code of setting height with auto-layout? – Vince Yuan Sep 16 '14 at 15:45
16

Widgets have their heights adjusted by the system. If you have defined your height using constraints this will be automatically adjusted as required. If you're using explicit layout you can request a new height by modifying the preferredContentSize of your widget.

Note that you have no guarantee notification center will respect your height request: it may be adjusted automatically, it may be adjusted but not to the exact height you want, or it may not be honored at all.

The best way to develop a widget is to use auto-layout constraints to set your height values, that way your widget will adapt to different heights with ease.

lxt
  • 31,146
  • 5
  • 78
  • 83
  • 1
    +1 for the explanation and thanks for the answer! but auto-layout unfortunately didn't work for me in this situation :/ – Gotschi Jun 04 '14 at 16:13
  • If you're having problems with auto-layout not updating the height of your extension I'd try 1) visualizing the constraints with the new debugging tools in Xcode (to make sure your constraints are doing what you think they're doing), and if everything looks fine, 2) filing a bug because it should 'just work'. – lxt Jun 04 '14 at 16:15
  • This is a very helpful answer. It explains why my widgets aren't always as tell as I expect them to be. But where did you read this? I have read all the Today extensions documentation and I don't recall reading the system may decide whether it should be big or not. – Andy Ibanez Jun 07 '14 at 18:31
  • 1
    It's in the header files for the Notification Center framework. – lxt Jun 07 '14 at 18:39
  • How do you set the height constraint in IB for autolayout? I have my Today VC and it's View, but I can't set a height constraint on the view. The view has two subviews and I have setup those constraints... – i_am_jorf Aug 14 '14 at 18:46
  • I'm not sure "The best way to develop a widget is to use auto-layout constraints to set your height values, that way your widget will adapt to different heights with ease." is valid in all contexts. How would you use autolayout to specify the height if you're pulling data over a network and the height will then be dynamically calculated? – Awesome-o Sep 11 '14 at 18:11
  • @Awesome-o: because auto-layout can allow for dynamic sizing to fit a view's content. – lxt Sep 11 '14 at 23:26
  • @jeffamaphone adding constraints to the subviews will determine the height, along with what iOS decides to allow. For instance, try adding a UILabel with 0 top and bottom margins and a set height to that main view. What I'm finding in practice is that I can get a height that is about one screenful of content. This kind of stinks for landscape mode on the iPhone where I'm only able to get a height of around 160 points. – Matt R Sep 12 '14 at 18:41
  • Yeah, I had some trouble with it; kept coming out at zero height. Then the designers changed everything and I re-did everything and it seems okay now. – i_am_jorf Sep 12 '14 at 20:03
16

Since iOS 10 extension's height is 110 pixels. You should use new protocol method widgetActiveDisplayModeDidChange:withMaximumSize: to extend extension size (Objective-C):

- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode
                         withMaximumSize:(CGSize)maxSize {

    if (activeDisplayMode == NCWidgetDisplayModeExpanded) {
        self.preferredContentSize = CGSizeMake(maxSize.width, 600.0);
    } else if (activeDisplayMode == NCWidgetDisplayModeCompact) {
        self.preferredContentSize = maxSize;
    }
}

Also you may need to call setWidgetLargestAvailableDisplayMode: on your extension context in today view controller's viewDidLoad method like this (Objective-C):

if ([self.extensionContext respondsToSelector:@selector(setWidgetLargestAvailableDisplayMode:)]) { // iOS 10+
    [self.extensionContext setWidgetLargestAvailableDisplayMode:NCWidgetDisplayModeExpanded];
} else {
    self.preferredContentSize = CGSizeMake(0, 600.0); // iOS 10-
}

This thread may be helpful https://forums.developer.apple.com/thread/48930

Lion
  • 1,264
  • 1
  • 17
  • 23
  • Bear in mind that the widget sizes (compact/expanded) are different on the iPad. Can't remember the exact values right now, but they are larger than the iPhone's widget size. – DPR Dec 09 '16 at 16:46
  • You also need to set `extensionContext?.widgetLargestAvailableDisplayMode = .expanded` in order to get expanded mode. – Enrico Susatyo Jan 12 '17 at 05:33
  • So how are we suppose to set it up if we want to support both below and above iOS10? – GeneCode Jan 21 '17 at 13:47
  • @Lion, it works for me But i also want to scroll my widget as i've taken tableview to showing my content and i am having list of data to displat in widget. Would you please help me out if having any idea? – Anjali jariwala Nov 21 '18 at 19:51
10

The best way is of course Autolayout but by default there are margins which you can control like this

func widgetMarginInsetsForProposedMarginInsets
    (defaultMarginInsets: UIEdgeInsets) -> (UIEdgeInsets) {
    return UIEdgeInsetsZero
}
lukas
  • 2,300
  • 6
  • 28
  • 41
Aleš Kocur
  • 101
  • 1
  • 2
8

There are two ways to display Today extension:

  1. Compact Mode (fixed height for Widget)
  2. Expand Mode (Variable height for Widget)

Whatever code you do to change the height of extension in Compact mode will not make any difference. So you need to change the mode from compact to Expand Mode.

// 1. Load This in viewDidLoad:

override func viewDidLoad() {
  super.viewDidLoad()
  self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded
}

// 2. Implement another widget protocol

func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize){
  if (activeDisplayMode == NCWidgetDisplayMode.compact) {
    self.preferredContentSize = maxSize;
  }
  else {
    self.preferredContentSize = CGSize(width: 0, height: 200);
  }
}

You can refer WWDC for more updates about App extensions

fAiSaL
  • 754
  • 1
  • 10
  • 29
1

Today widget default UIEdgeInsets defaultMarginInsets (UIEdgeInsets) defaultMarginInsets = (top = 0, left = 44, bottom = 39, right = 0)

You should add this method

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 44, 0, 0);
return edgeInsets;}
Vivek
  • 4,916
  • 35
  • 40