31

I am working on a Today Extension with a dynamically sized table. I have been able to get the table to resize for the content using:

    self.preferredContentSize = accountsTable.contentSize

However, I have found that it will not get taller than a certain size (568 px) even though I can tell the table contentSize is larger.

I'm not clear if this is a built-in limit or if there is a way around this to make a larger view. It appears that some previous extensions (Stocks widget) is able to become larger.

Anyone else running into the same behavior. Anyone know if it's possible to make an extension appear larger either immediately or using a "Show All" button like the Stock widget?

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
user2816488
  • 325
  • 3
  • 4
  • 1
    Same here. Worse still, it's reporting 568 px as height even though the view I'm allowed to render is way less on screen, making dynamic layouts a pain. – Rick Jul 21 '14 at 15:10

5 Answers5

15

I made some tests and you can calculate the maximum height of your Today Extension with this formular:

for iPhone:

float maxHeight = [[ UIScreen mainScreen ] bounds ].size.height - 126;

for iPad:

float maxHeight = [[ UIScreen mainScreen ] bounds ].size.height - 171;

This should work for alle Screen sizes...

Urkman
  • 1,298
  • 1
  • 16
  • 32
  • 1
    My tests seem to agree with this. Thanks! – Stephen Oct 14 '14 at 19:54
  • Well actually, works for iPhone only. iPad seems to be different – Stephen Oct 14 '14 at 20:18
  • 1
    You are assuming the bottom margin to be 10. For example for iPhone 6 in landscape mode the available height is 375 (750 pixels). So we need to subtract the heights of the following: height of the today/notification segmented control bar(53), the app extension section header (32), bottom arrow bar(31) & the bottom margin (10) = 126. – Gamma-Point Feb 02 '15 at 21:00
  • I wouldn't use this method going forward, please see my answer – MobileMon Apr 24 '19 at 18:59
6

Ok, although you can assign to the preferredContentSize any CGSize it is reduced to max height and width.

Device Orientation (max width, max height):

iPhone 5S Portrait (272, 441.5)
iPhone 5S Landscape (520, 205.5)

iPhone 6 Portrait (327, 540.5)
iPhone 6 Landscape (586, 260.5)

iPhone 6 Plus Portrait (362, 610)
iPhone 6 Plus Landscape (585, 288)

iPad Mini Portrait (535, 853)
iPad Mini Landscape (535, 597)

iPad Portrait (711, 985)
iPad Landscape (967, 729)

How did I get these values?

@IBOutlet weak var sizerView: UIView!

inside viewDidLoad:

preferredContentSize = CGSizeMake(0, 2000)
dispatch_after(1, dispatch_get_main_queue(), { //it needs time to render itself
    label.text = NSStringFromCGSize(self.sizerView.bounds.size) //here you have MAX VALUES
}
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
4

It seems, that iOS is adding an UIView-Encapsulated-Layout-Height constraint to your own constraints:

(
    "<NSLayoutConstraint:0x610000280640 V:[_UILayoutGuide:0x7f92d0513810]-(500)-[UILabel:0x7f92d040cb20'Hello World']>",
    "<NSLayoutConstraint:0x610000280690 V:[UILabel:0x7f92d040cb20'Hello World']-(500)-[_UILayoutGuide:0x7f92d0515100]>",
    "<_UILayoutSupportConstraint:0x6100002a2f40 V:[_UILayoutGuide:0x7f92d0513810(0)]>",
    "<_UILayoutSupportConstraint:0x6100002a2ee0 V:|-(0)-[_UILayoutGuide:0x7f92d0513810]   (Names: '|':UIView:0x7f92d040c810 )>",
    "<_UILayoutSupportConstraint:0x6100002a3000 V:[_UILayoutGuide:0x7f92d0515100(0)]>",
    "<_UILayoutSupportConstraint:0x6100002a2fa0 _UILayoutGuide:0x7f92d0515100.bottom == UIView:0x7f92d040c810.bottom>",
    "<NSLayoutConstraint:0x60800009e780 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7f92d040c810(628)]>"
)

This constraint forces the widget to have the maximum height. You can get it's value like this:

- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {

    for (NSLayoutConstraint *constraint in self.view.constraints) {
        if ([constraint.identifier isEqualToString:@"UIView-Encapsulated-Layout-Height"]) {
            NSLog(@"Height: %@", @(constraint.constant));
        }
    }

    completionHandler(NCUpdateResultNewData);
}
gklka
  • 2,459
  • 1
  • 26
  • 53
1

To get the max height of the widgets active display mode, do this in your UIViewController:

let context = self.extensionContext
if let context = context{
    let height = context.widgetMaximumSize(for: context.widgetActiveDisplayMode).height
}

To get the max height of expanded and compact individually regardless of the current display mode, do this:

var context = self.extensionContext
if let context = context{
    let compactHeight = context.widgetMaximumSize(for: .compact).height
    let expandedHeight = context.widgetMaximumSize(for: .expanded).height
}
MobileMon
  • 8,341
  • 5
  • 56
  • 75
-3

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

It seems the 568px is just the maxheight of your iPhone 5 and not the actual size. As far as I could figure out there is no way to get the real size.

Notive
  • 51
  • 1
  • 1
    Autolayout doesn't solve the case when you need to display something like "Show All" button. – Andriy Oct 14 '14 at 13:18