Why is SwiftUI picker in form repositioning after navigation?
Asked Answered
J

4

22

After clicking the picker it navigates to the select view. The item list is rendered too far from the top, but snaps up after the animation is finished. Why is this happening?

Demo: https://gfycat.com/idioticdizzyazurevase

I already created a minimal example to rule out navigation bar titles and buttons, form sections and other details:

import SwiftUI

struct NewProjectView: View {

    @State var name = ""

    var body: some View {
        NavigationView {
            Form {
                Picker("Client", selection: $name) {
                    Text("Client 1")
                    Text("Client 2")
                }
            }
        }
    }
}

struct NewProjectView_Previews: PreviewProvider {
    static var previews: some View {
        NewProjectView()
    }
}

This happens in preview mode, simulator and on device (Xcode 11.2, iOS 13.2 in simulator, 13.3 beta 1 on device).

Jess answered 8/11, 2019 at 20:55 Comment(7)
There is a fairly recent video on YouTube demonstrating basic forms in SwiftUI, it‘s working there, so I guess it‘s not a bug in SwiftUI itself: youtu.be/Ho88Eid9gi0?t=573Jess
Same issue - very annoying. If you use inline style for nav bar it goes away.Aplanatic
... also the text in the cells jumps - about 4 px to the rightAplanatic
@DogCoffee: I debugged the horizontal jumping to be changing insets. This can be fixed by explicitly setting them with .listRowInsets().Jess
much appreciated, works great.Aplanatic
I ran into this issue too when i was playing around on Xcode 11.4.1. I decided to download the latest Xcode beta (11.5 beta 2) / iOS 13.5 to see if it had fixes in for it. iPhones with notches (like 11) don't reposition anymore, but iPhones without notches (SE 2) still have this behavior. Hopefully apple fixes this in later betas / 11.5 release.Leeann
This is still a bug I think - If you have this exact example using the SE simulator the form jumps.Tutorial
J
11

The obviously buggy behavior can be worked around when forcing the navigation view style to stacked:

NavigationView {
    …
}.navigationViewStyle(StackNavigationViewStyle())

This is a solution to my problem, but I won‘t mark this as accepted answer (yet).

  1. It seems to be a bug, even if it may be triggered by special circumstances.
  2. My solution won‘t work if you need another navigation view style.
  3. Additionally, it won‘t fix the horizontal repositioning mentioned by DogCoffee in the comments.
Jess answered 21/11, 2019 at 19:20 Comment(1)
This also is useful if your app runs on iPads, otherwise your modal views present as a master - detail split view.Aplanatic
U
5

In my opinion, it has something to do with the navigation bar. In default (no mention of .navigationBarTitle extension), the navigation display mode is set to .automatic, this should be amend to .inline. I came across another post similar to this and use their solution to combine with yours, by using .navigationBarTitle("", displayMode: .inline) should help.

import SwiftUI

struct NewProjectView: View {

    @State var name = ""

    var body: some View {
        NavigationView {
            Form {
                Picker("Client", selection: $name) {
                    Text("Client 1")
                    Text("Client 2")
                }
            }
            .navigationBarTitle("", displayMode: .inline)
        }
    }
}


struct NewProjectView_Previews: PreviewProvider {
    static var previews: some View {
        NewProjectView()
    }
}
Urnfield answered 3/1, 2020 at 7:32 Comment(1)
This works around the issue, but it also changes the title style which is not desired in my case.Jess
S
3

Until this bug is resolved another way to work around this issue while retaining the DoubleColumnNavigationViewStyle for iPads would be to conditionally set that style:

let navView = NavigationView {
    …
}
if UIDevice.current.userInterfaceIdiom == .pad {
    return AnyView(navView.navigationViewStyle(DoubleColumnNavigationViewStyle()))
} else {
    return AnyView(navView.navigationViewStyle(StackNavigationViewStyle()))
}
Schaefer answered 10/12, 2019 at 18:59 Comment(0)
J
1

Thanks for this thread everyone! Really helped me understand things more and get a hold of one of my problems. To share with others, I was having this problem to but I was also having this problem when I set a section to appear in a if/else statement set on a section with a toggle. When the toggle was activated it would shift the section header horizontally a few pixels.

The following is how I fixed it

Section(header: Text("Subject Identified").listRowInsets(EdgeInsets()).padding(.leading)) {
                Picker(selection: $subIndex, label: Text("Test")) {
                    ForEach(0 ..< subIdentified.count) {
                        Text(self.subIdentified[$0]).tag($0)
                    }
                }
            .labelsHidden()
            .pickerStyle(SegmentedPickerStyle())

I'm still having horizontal shift on my picker selection view and not sure how to fix. I created another thread to received input. Thanks again! SwiftUI Shift Picker Text Horizontal

Joab answered 27/4, 2020 at 5:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.