Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change UISplitViewController displayMode property when entering multitasking? (iOS 14)

Tags:

How can I detect when iPad multitasking (i.e. another app brought on screen, side-by-side with my app) becomes active?

I have a UISplitViewController with the following parameters set up as below:

preferredDisplayMode = .twoBesideSecondary
preferredSplitBehavior = .tile
setViewController(SidebarVC(), for: .primary)
setViewController(SuppVC(), for: .supplementary)
setViewController(SecondaryVC(), for: .secondary)

In landscape orientation, there is plenty of room for all 3 columns (.primary, .supplementary, .secondary). In portrait or when multitasking, the screen width is narrower and my 3rd column (.secondary) gets squished to a very narrow width. The horizontal size class remains regular so I can't use that to detect it. (When horizontal size class becomes compact, my UISplitViewController.compact shows and works just fine).

I'm wanting to change the UISplitViewController.displayMode property to .twoDisplaceSecondary when the screen is narrower, but the horizontal size class remains regular (i.e. when in portrait, or when another app is in multitasking). This would allow the 3rd column to be pushed off-screen (displaced) rather than squished.

A perfect example of the exact behavior I'm looking for is the Contacts app on iPad in iOS 14. It uses a triple column layout, seemingly with a displayMode of .tile. When the app is full screen in landscape, all 3 columns are displayed and there is enough room for no squishing to occur. However, if you bring another app into multitasking (thus making the Contacts app width narrower, but horizontal size class remains regular), the displayMode seems to change to .twoDisplaceSecondary, and the 3rd column is pushed off-screen rather than being squished.

I think I can manage orientation changes via viewWillTransitionToSize() method, but I haven't been able to find a delegate or other way to detect when the app is narrower, but still with a .regular horizontal size class, like the Contacts app, is seemingly able to do.

Screenshots to show what I'm referencing: Contacts app w/ triple columns, full screen width Contacts app in multitasking, with 3rd column, displaced

You can see that in the second screenshot, the 3rd column is displaced rather than squished when there isn't enough space.

like image 851
dank_muffin Avatar asked Jul 04 '20 18:07

dank_muffin


2 Answers

I figured out that it's important to set BOTH .preferredDisplayMode and .preferredSplitBehavior when the view transitions. Setting just one or the other will result in lots of weird behavior.

For future readers, what I figured out works for this case is setting preferredDisplayMode = .twoBesideSecondary and preferredSplitBehavior = .tile when the screen is wide enough, then set preferredDisplayMode = .oneBesideSecondary and preferredSplitBehavior = .displace when the screen is narrow. I used a function that checks if the view.frame.size.width < 1194 to determine if the screen is full width or not, as using orientation only would cause problems if the app is side by side with another. I call this in viewDidLoad as well as viewWillTransition(toSize:).

like image 67
dank_muffin Avatar answered Oct 02 '22 15:10

dank_muffin


viewWillTransitionToSize has a size param containing the width. Usually you would check for a width less than 1024.

like image 26
malhal Avatar answered Oct 02 '22 15:10

malhal