1

I created a custom horizontal scroll, which uses animation to scroll. When the view is presented, it uses animation to present the views.

So when I invoke the view and the onAppear is initiated, it changes the offset with animation, But this behavior is unwanted. I don't want to animate my view when they are created.

I tried to create @State variable

    @State private var myBool = false

and create a condition:

     .animation(self.myBool ? Animation.spring : .none)

and then inside .onAppear

     .onAppear(
         ...
            some code that changing state variables
         ...
         self.myBool = true
     )

but it didn't work, it still uses the animation even when myBool is false

How can I allow animation only AFTER the body is created? I mean, is there a modifier .onFinish?

This is an example of the code:

   struct scroll: View {
       @State var offset: 0

       var body: some View {
          GeometryReader { geo in
              HStack {

                   ForEach(0..<5) { i in
                       Rectangle()
                   }

               }
                .gesture(DragGesture()
                 .onChange ({ (value) in
                     self.offset = value.translation.width
                 }
                 .onEnded ({ _ in
                     self.offset = 50

                 }


            )
            .offset(x: self.offset)
            .animation(.spring)
            .onAppear (
                self.offset = geo.size.width
            )
            }
       }
   }
Kevin
  • 1,103
  • 10
  • 33
  • https://stackoverflow.com/questions/56496359/swiftui-view-viewdidload – Enes Karaosman May 15 '20 at 15:20
  • I'm not sure I understood the problem. Would you provide some working demo code or screen recording of undesired effect to be removed? – Asperi May 15 '20 at 15:25
  • I edited the code example I got animation when the onChange is applied and also onEnded And also onAppear uses animation because it changes the offset My issue is that I dont want to use animation in the onAppear – Kevin May 15 '20 at 15:34

3 Answers3

1

Maybe I am misunderstanding your question, but if you don't want any animation onAppear, why don't you initialize your offset with 150? Instead you start with 0 and set it to 150 onAppear which seems to be the reason for the animation because the variable changes onAppear.

Kuhlemann
  • 3,066
  • 3
  • 14
  • 41
  • Yes this is a good solution But I am using geometry reader. I can't modify the offset outside the geometry reader so I need to use onAppear I will update the sample code – Kevin May 15 '20 at 16:39
1

As I see now you just need to set initial value directly

struct scroll: View {
    var body: some View {
        GeometryReader { geo in
            innerScroll(offset: geo.size.width) // << here !!
        }
    }

    struct innerScroll: View {        // inner subview
        @State var offset: CGFloat

        var body: some View {
            HStack {
                ForEach(0..<5) { i in
                    Rectangle()
                }
            }
            .gesture(DragGesture()
            .onChanged { (value) in
                self.offset = value.translation.width
            }
            .onEnded { _ in
                self.offset = 50

                }
            )
                .offset(x: self.offset)
                .animation(.spring())
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Yes this is a good solution But I am using geometry reader. I can't modify the offset outside the geometry reader so I need to use onAppear I will update the sample code – Kevin May 15 '20 at 16:39
  • @Kevin, anyway it better to do via initialisation, just a bit differently - see updated. – Asperi May 15 '20 at 17:00
1
 VStack{
        ScrollView(.vertical, showsIndicators: false) {
            VStack{

             }
       }      
    }.onAppear(perform: {
         
        print("Evento On Create / apertura")
         
    
    })
    .onDisappear( perform: {
        print("Evento Chiusura Form")
        showMenu = false
    })