Fix odd DatePicker animation behaviour in SwiftUI form
Asked Answered
W

3

5

I'm getting some odd animation behaviour with DatePickers in a SwiftUI form. A picture is worth a thousand words, so I'm sure a video is worth a million words: https://i.sstatic.net/bNrTK.jpg

I'm trying to get the date picker to expand and then collapse within the form, exactly like the behaviour when creating a new event in Calendar.app

What is happening for me is:

  1. Any expanding item in a Section (other than the last one) will open normally, but when it closes the expanded part slides down and fades, instead of sliding up and fading.
  2. The last item in the section slides correctly but doesn't fade at all. It simply appears and then disappears at the start/end of the transition

These behaviours only happen if there is a non-DatePicker element (e.g. Text, Slider) somewhere in the form (doesn't have to be in that particular section)

Here's my ContentView:

struct ContentView: View {
    @State var date = Date()
    @State var isDateShown = false
    var body: some View {
            Form {
                Section(header: Text("Title")) {
                    DatePicker("Test", selection:$date)
                    DatePicker("Test", selection:$date)
                    Text("Pick a date").onTapGesture {
                        withAnimation {
                            self.isDateShown.toggle()
                        }
                       
                    }
                    if(isDateShown) {
                        DatePicker("", selection: $date).datePickerStyle(WheelDatePickerStyle()).labelsHidden()
                    }
                    
                }
                Section(header: Text("hello")) {
                    Text("test")
                }
        }
        
    }
}

Happy to provide anything else required

Wisp answered 25/6, 2020 at 7:40 Comment(1)
disabling the implicit animations on the Form with .animation(nil) is a bit of an improvement, but still not greatJeromejeromy
C
8

Here are two possible workarounds for iOS <14: 1) simple one is to disable animation at all, and 2) complex one is to mitigate incorrect animation by injecting custom animatable modifier

Tested both with Xcode 11.4 / iOS 13.4

1) simple solution - wrap DatePicker into container and set animation to nil

demo1

VStack {
    DatePicker("Test", selection:$date).id(2)
}.animation(nil)

2) complex solution - grab DatePicker changing frame using a) view preference reader ViewHeightKey and b) animate this frame explicitly using AnimatingCellHeight from my other solutions.

demo2

struct TestDatePickersInForm: View {
    @State var date = Date()
    @State var isDateShown = false
    @State private var height = CGFloat.zero
    var body: some View {
            Form {
                Section(header: Text("Title")) {
                    // demo of complex solution
                    VStack {
                        DatePicker("Test", selection:$date).id(1)
                            .background(GeometryReader {
                                Color.clear.preference(key: ViewHeightKey.self,
                                    value: $0.frame(in: .local).size.height) })
                    }
                    .onPreferenceChange(ViewHeightKey.self) { self.height = $0 }
                    .modifier(AnimatingCellHeight(height: height))
                    .animation(.default)

                    // demo of simple solution
                    VStack {
                        DatePicker("Test", selection:$date).id(2)
                    }.animation(nil)

                    Text("Pick a date").onTapGesture {
                        withAnimation {
                            self.isDateShown.toggle()
                        }

                    }
                    if(isDateShown) {
                        DatePicker("", selection: $date).datePickerStyle(WheelDatePickerStyle()).labelsHidden().id(3)
                    }

                }
                Section(header: Text("hello")) {
                    Text("test")
                }
        }

    }
}
Challis answered 30/6, 2020 at 5:42 Comment(1)
.animation(nil) is gold!Arbuthnot
L
0

Funny enough.. with the new beta, they apparently changed the DatePicker.

enter image description here

So if you have no problem with iOS 14+ only...

Llama answered 25/6, 2020 at 11:5 Comment(2)
I know. Unfortunately, the project we are working on can't have this bug there while we wait for iOS 14.Wisp
Do you know, how can I do this same animation for my own custom viewJustifier
B
0

closest solution is to move the datepickers to its own sections

Form {
            Section(header: Text("Title")) {
                
                DatePicker(selection:$date1, label: {Text("Test")}    )
                
            }
            DatePicker("Test", selection:$date2)
            Section{
                Text("Pick a date").onTapGesture {
                    withAnimation {
                        self.isDateShown.toggle()
                    }
                    
                }
                if(isDateShown) {
                    DatePicker("", selection: $date3).datePickerStyle(WheelDatePickerStyle()).labelsHidden()
                }
            }
            Section(header: Text("Hello")){
                Text("Hello")
            }
        }
Butters answered 26/6, 2020 at 0:53 Comment(1)
am still seeing the weird animation unfortunately.Wisp

© 2022 - 2024 — McMap. All rights reserved.