fermoya / SwiftUIPager

Native Pager in SwiftUI
MIT License
1.29k stars 172 forks source link

[BUG] Custom pagingAnimation not working as expected? #118

Closed fermoya closed 4 years ago

fermoya commented 4 years ago

Hi

When scrolling through my pages, i use the following animation: .pagingAnimation { (_) -> PagingAnimation in return .custom(animation: .interactiveSpring()) }

When I use the following animation to switch between pages: withAnimation(.interactiveSpring()) { self.currentIndex += 1 }

I don't get the same animation, any ideas how to fix this?

Originally posted by @VanHoutte in https://github.com/fermoya/SwiftUIPager/issues/67#issuecomment-683391831

fermoya commented 4 years ago

@vanhoutte can you share a complete View to see the issue, please? I think the effect is going to be slightly different. If you page manually via a Button click, then the items are at their original position whereas if dragging the translation is shorter. A spring will most likely bounce more when dragging.

If you send me some more code I can confirm but you might need to alter the spring values based on the translation and velocity

VanHoutte commented 4 years ago

   struct OnBoardingViewPager: View {
        @ObservedObject var viewModel: OnBoardingViewModel
        @State var page: Int = 0
        var items = Array(0..<5)

        var body: some View {
            GeometryReader { geometry in
                VStack {
                    VStack {
                        Pager(page: self.$viewModel.currentIndex,
                              data: Array(0..<self.viewModel.onBoardingPages.count),
                              id: \.self,
                              content: { index in
                                OnBoardingViewPage(pageIndex: index,
                                                   page: self.viewModel.onBoardingPages[index])
                        })
                            .delaysTouches(false)
                            .pagingAnimation { (_) -> PagingAnimation in
                                return .custom(animation: .interactiveSpring())
                        }

                        KAPageControl(index: self.viewModel.currentIndex,
                                      maxIndex: self.viewModel.onBoardingPages.count - 1)
                    }
                    .padding(.top, geometry.safeAreaInsets.top)
                    .padding(.bottom, geometry.safeAreaInsets.bottom)
                }
                .background(Color.white)
            }
            .edgesIgnoringSafeArea(.vertical)
        }
    }

This is a button inside a page

        HStack {
            Button(action: {
                withAnimation(.interactiveSpring(dampingFraction: 0.85)) {
                    self.currentIndex += 1
                }
            }) {
                Text(NSLocalizedString("general.skip", comment: "First onboarding screen subtitle"))
            }
            .buttonStyle(KADarkButtonStyle())
            .frame(maxWidth: .infinity)
        }

Indeed, if i change the dampingFraction to a lower value, I get the sprint effect. Any idea how to calculate the exact amount?

fermoya commented 4 years ago

Hi @VanHoutte , that’s something you need to figure out yourself. In a beginning, I thought of doing that calculation myself but it would be me assuming the right behavior and that’s not right.

It’s not just the dampingFraction, there are other parameters that affect a spring animation. It’s easier for an easeIn for example, it’s just a matter of modifying the duration. In case of a spring, that depends on the dampingFraction, blendDuration, ...

VanHoutte commented 4 years ago

Thanks for the quick replies! I updated the parameters for the interactiveSpring to match the swipe, it's almost identical. Thanks again for the help!

fermoya commented 4 years ago

You’re welcome. I’ll close this issue then