Hi,
I've a widget which changes it's size bases on some user-preferences and over the time without any userinput. I wonder how to decide what NCWidgetDisplayMode to set for widgetLargestAvailableDisplayMode.
I know the height of the content the widget is able to display but I don't know a method to query the maximum height for compact mode.
So let's assume the widget is currentöy displayed expanded.
The next time the widget is displayed the content has changed and will fit into the compact size.
The widget is displayed and widgetActiveDisplayModeDidChange is called once with activeDisplayMode == expanded (because the widget was expanded the last time it was shown) and a size which is way to large for the current content.
I now need to know, if the current content's height is smaller than the height in compact mode, becaus it doesn't makes sense to keep the widgetLargestAvailableDisplayMode set to expanded.
What's the way to handle this?
Dirk
From my testing it seems a compact widget will always be 110 points tall on all devices. The width will vary on device (and even which column it is in when shown in landscape on iPad).
I don't think you can programmatically switch between compact and expanded modes. Although maybe setting the largestAvailableDisplayMode to Compact when currently in Expanded would presumably switch. I expect the "Show More/Less" button would disappear then. I think if your widget could ever need more than 110 points it's best to set the largestAvailableDisplayMode to Expanded.
In my opinion, a user who leaves the widget expanded (i.e. the button is Show Less) is expressing a desire to see all the information. If you currently don't have much information, then the widget will appear at the smaller size (it can never be smaller than 110 points tall, no matter what your preferredContentSize height is). But when your content changes, the widget will grow automatically (since it is in Expanded mode). A user who leaves the widget in compact mode (showing Show More), is expressing an intent to always have the smaller size, no matter what the content is. It's subtle behaviour, but I think trying to be clever and adjusting largestAvailableDisplayMode depending on whether the current content will fit into the compact size or not will confuse thinigs.
I've not tested it, but if I leave the widget in expanded, the content shrinks (and you make the max size compact), the content expands again (and you make the max size expanded), will the widget be left in the compact mode? If that happens, a user who left it expanded suddenly finds themself in the compact mode just because there was an intermediate content size change that happened to be small enough to fit compact. The start and end sizes were all bigger than compact, but the small intermediate size effectively forced the widget into compact, even though the user had left it at expanded. (This is all a theory - I haven't tested this!)
To answer your actual question :-)
You can find the maximum size for compact or expanded using NSExtensionContext's widgetMaximumSizeForDisplayMode. Your widget's view controller has an extensionContext property that will return the NSExtensionContext. The NSExtensionContext's widgetActiveDisplayMode tells you which mode is currently being shown (and is read only).
You can change your preferredContentSize seemingly at any time and that will adjust what is displayed. So, if your content changes size, set it to your new size and the widget will change size (if expanded) to adjust. If you set a size that is too big to show (because it is bigger than the maximum that the current mode supports), your content will be cropped.
From my testing, when you want to change the content size it seems safest to get the maximum size that is supported by the display mode (this is passed as a parameter to widgetActiveDisplayModeDidChange:withMaximumSize:) and then set preferredContentSize to the width it provides and the height to whichever is the smallest of the maximum size or your content size.
CGSize preferredSize = [self.extensionContext widgetMaximumSizeForDisplayMode:self.extensionContext.widgetActiveDisplayMode];
self.preferredContentSize = CGSizeMake(preferredSize.width, MIN(preferredSize.height, self.tableView.contentSize.height));
Geoff.