Home > Enterprise >  Programmatically Collapse NavigationSplitView to One Column
Programmatically Collapse NavigationSplitView to One Column

Time:09-08

I have developed a SwiftUI NavigationSplitView app with two columns and it works as expected. I have chosen dynamic fonts and crafted the visual elements to respond to user settings for visual accessibility. I know that a number of the users who will employ this app will have the font size set to the largest available. While that enhances their view of the detail screen, it pretty much makes the sidebar unreadable. I'm trying to find a way to change the app's behavior based on the size of the dynamic type. Specifically, I'd like to have the iPad behavior the same as an iPhone behavior based on a font size that I define. As it is, the app on an iPhone collapses to a single column. I have not been able to find a way to programmatically do this on an iPad.

I have tried:

Setting the horizontalSizeClass and as expected, this is a getter only. .horizontalSizeClass = .compact

I have tried setting the column width of the detail to 0. .navigationSplitViewColumnWidth(0) that does not work

I have tried using the old stack function. .navigationViewStyle(StackNavigationViewStyle()) that does not work.

Clearly, this can be done, since it is automatic when the device is an iPhone. I guess I could create two views - one stacked and one split and choose based on a State variable but that seems a bit crude.

Any guidance would be appreciated. Xcode 14 beta 6, iOS 16

CodePudding user response:

This is a great idea and can be achieved by overriding the horizontalSizeClass in the environment depending on the environment value of dynamicTypeSize as follows:

struct NavigationSplitViewTest: View {
    @Environment(\.dynamicTypeSize) var dynamicTypeSize

    var body: some View {
        ViewContainingSplitView()
            .environment(\.horizontalSizeClass, dynamicTypeSize > .large ? .compact : .none)
    }
}

I tested it by launching the app on iPad simulator and it was in 2 column, then switching to Settings to increase the type size by one notch then back to app and it had switched to single column. However when attempting to switch the size back I noticed the show/hide column button disappeared so I think we have some feedback to submit.

CodePudding user response:

I still have not found an elegant way to do this, but my solution here does work.

Basically, I code for NavigationSplitView and for NavigationStack and change based on the Environment(.dynamicTypeSize). Like this:

if dynamicTypeSize <= .xxLarge {
    NavigationSplitView(columnVisibility: $columnVisibility) {
    //all the code
    } detail: {
    //all the code
    }
} else {
    NavigationStack {
    //all the code
    }
}

For others, I was confused by the terms involved here. There is DynamicTypeSize, dynamic fonts and Larger Accessibility Sizes. Dynamic fonts are those pre-built fonts that support dynamic type out of the box - .title, .headline, .body etc. Dynamic type size is the slider in settings that allows the user to scale the dynamic fonts to suit their needs - all the dynamic fonts scale with the slider setting. Then on top of the slider in settings for these pre-made fonts, is the option for Larger Accessibility sizes which gives the user even bigger options.

My scheme above supports all of those intermingled options for both iPad and iPhone.

  • Related