PageView icon indicating copy to clipboard operation
PageView copied to clipboard

Page snapping not working

Open danpalmer opened this issue 2 years ago • 5 comments

I may have misunderstood what's happening here, but hopefully a video demo will help show what the issue is. Essentially when I swipe on a page, I can see the next page, but when I stop swiping the pages just stay in the half-transitioned state instead of snapping to either the new or current page based on the threshold.

import PageView
import SwiftUI

public struct ImageCarouselView: View {
    let imageURLs: [URL]

    @State private var index: Int = 0

    public var body: some View {
        HPageView(selectedPage: $index, data: imageURLs) { imageURL in
            CachedImage(imageURL) // Kingfisher image view
            // Text(imageURL.absoluteString) // Same problem
        }
    }
}

// For the purposes of demonstration code
extension URL: Identifiable {
    var id: String { absoluteString }
}
ImageCarouselView(imageURLs: imageURLs)
    .frame(width: width, height: width * 4 / 3)

As far as I can tell from the docs this should work as-is. I've tried passing each of the different pageGestureTypes to the constructor, and also tried some extreme settings for pageSwitchThreshold (0.1 and 0.9), but neither of these seems to have any effect.

I thought that there could be some issue with an interactor above this component in the view hierarchy, but there's nothing obvious that stands out to me, and I'm not quite sure what to look for. This view originally had an onTapGesture handler on it, but I removed that to narrow down the problem.

Here's a video of the issue. It's from the simulator for ease of recording, but the same behaviour happens on a real device.

https://user-images.githubusercontent.com/202400/138448200-131f5301-4195-4678-85a7-d31b493e4353.mov

iOS: 14.5, Xcode: 13.0. PageView: 1.5.0

Happy to provide any more information that may help diagnose this!

danpalmer avatar Oct 22 '21 11:10 danpalmer

Hi, sorry for the delay. Unfortunately I cannot reproduce the issue. The simple demos from Examples/ work as expected on iOS 14.2 and iOS 15.2 (which are very similar to your simple case), compiled using Xcode 12.3/13.2 Could you provide simple project with the issue along with xcode/simulator version? Meanwhile I'm gonna try it on iOS 14.5, maybe it's happening only on specific OS versions.

EDIT: On iOS 14.5, Xcode 13.2 page snapping works fine

fredyshox avatar Dec 16 '21 22:12 fredyshox

Hi, I ran into the same issue.

I figured out the reason. It seems pretty bizarre that this happens.

I removed all @EnvironmentObject and private properties in the class or view struct and moved the PageView object into a new struct view. This resolved my issue.

Hope this helps.

pradeep-spikey-tech avatar Feb 02 '22 13:02 pradeep-spikey-tech

@pradeep-spikey-tech Hmmm, could you provide example View that causes that? Also what version of Xcode and iOS are you running?

fredyshox avatar Feb 02 '22 13:02 fredyshox

@fredyshox Below is an example, I had created a page view with this format which caused the issue. Only @EnvironmentObject var , let and private let properties cause issues, not @State private var or private var.

import PageView

struct UI_View: View {

@EnvironmentObject var controller: Controller

private let theme = PageControlTheme(
            backgroundColor: .clear,
            dotActiveColor: Color("someColor"),
            dotInactiveColor: .gray,
            dotSize: 10.0,
            spacing: 12.0,
            padding: 0.0,
            //        xOffset: 8.0,
            //        yOffset: -8.0,
            xOffset: 0.0,
            yOffset: 0.0,
            alignment: Alignment(horizontal: .center, vertical: .bottom)
        )

var body: some View {

HPageView(selectedPage: $selectedPage, data: 0..<3, theme: theme) { index in
            
            RoundedRectangle()
        .frame(minHeight: 180, maxHeight: 220, alignment: .center)
        .aspectRatio(contentMode: ContentMode.fill)

}

}

I moved the HPageView into a separate View Struct and changed the code structure as follows and it worked:

import PageView

struct UI_View: View {

@EnvironmentObject var controller: Controller

private let theme = PageControlTheme(
            backgroundColor: .clear,
            dotActiveColor: Color("someColor"),
            dotInactiveColor: .gray,
            dotSize: 10.0,
            spacing: 12.0,
            padding: 0.0,
            //        xOffset: 8.0,
            //        yOffset: -8.0,
            xOffset: 0.0,
            yOffset: 0.0,
            alignment: Alignment(horizontal: .center, vertical: .bottom)
        )

var body: some View {

UI_PageView()

}
}

struct UI_PageView: View {

@State private var someStateVariable: SomeStateVariable!

var body: some View {

let theme = PageControlTheme(
            backgroundColor: .clear,
            dotActiveColor: Color("someColor"),
            dotInactiveColor: .gray,
            dotSize: 10.0,
            spacing: 12.0,
            padding: 0.0,
            //        xOffset: 8.0,
            //        yOffset: -8.0,
            xOffset: 0.0,
            yOffset: 0.0,
            alignment: Alignment(horizontal: .center, vertical: .bottom)
        )

HPageView(selectedPage: $selectedPage, data: 0..<3, theme: theme) { index in
            
            RoundedRectangle()
        .frame(minHeight: 180, maxHeight: 220, alignment: .center)
        .aspectRatio(contentMode: ContentMode.fill)

}

}
}

pradeep-spikey-tech avatar Feb 07 '22 13:02 pradeep-spikey-tech

It looks as if there was something funky going on with changing the pageIndex binding.

Although I've tried with data: Range<Int>, only the first swipe works correctly. After that, every attempt to change the page results the view remaining in the in-between state described by @danpalmer.

syrekable avatar Jul 04 '22 15:07 syrekable