Koraktor
Koraktor

Reputation: 42893

Why is SwiftUI picker in form repositioning after navigation?

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).

Upvotes: 22

Views: 3611

Answers (4)

Sean
Sean

Reputation: 43

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

Upvotes: 1

Brandon C.
Brandon C.

Reputation: 420

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()))
}

Upvotes: 3

np2314
np2314

Reputation: 685

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()
    }
}

Upvotes: 5

Koraktor
Koraktor

Reputation: 42893

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.

Upvotes: 11

Related Questions