【问题标题】:Index unexpectedly changes when trying to make Swipeable Image View with SwiftUI尝试使用 SwiftUI 制作可滑动的图像视图时,索引意外更改
【发布时间】:2021-08-11 11:35:19
【问题描述】:

我正在尝试使用 SwiftUI 制作可滑动的图像视图。 向左/向右滑动可将图像向左/向右移动,当您滑动足够长的时间时,图像会滑开并出现下一张/上一张图像:就像主屏幕选项卡一样。 点击左/右使上一张/下一张图像替换当前图像,但没有动画。

此视图获取图像数组、索引和图像偏移量。

其他一些视图检测到滑动手势并更改索引。 问题是,当滑动手势更改索引和图像幻灯片时,索引在动画开始后立即更改,而不是在动画完成后更改。

看来var currentIndex = index是这个bug的根源,bug如何修复?

struct MyImagesView: View {
    @Binding var index:Int
    let imgArray:[URL]
    @Binding var dragOffset:CGSize
    @State var nextindex:Int = 1
    @State var screenSize:CGRect = UIScreen.main.bounds
    var body: some View {
        var currentindex = index
        let insertionAnimation: ()->AnyTransition = { nextindex > currentindex ? AnyTransition.move(edge: .leading) : AnyTransition.move(edge: .trailing) }
        let removalAnimation: ()->AnyTransition = { nextindex < currentindex ? AnyTransition.move(edge: .trailing) : AnyTransition.move(edge: .leading) }
        ZStack {`enter code here`
            MyImageView(array: imgArray,index:currentindex-2).offset(x: -screenSize.width, y: 0)
            MyImageView(array: imgArray,index:currentindex-1)
            MyImageView(array: imgArray,index:currentindex).offset(x: screenSize.width, y: 0)
        }
        .offset(dragOffset)
        .onAppear(perform: { nextindex = index })
        .onChange(of: index, perform: { value in
            if dragOffset.width != 0 && value != currentindex {
                nextindex = value
                Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { _ in dragOffset = .zero; currentindex = value })
                dragOffset.width = nextindex>currentindex ? -screenSize.width : (nextindex < currentindex ? screenSize.width : 0)
            }
        })
        .transition(.asymmetric(insertion: insertionAnimation(), removal: removalAnimation()))
        .animation(.linear(duration: (dragOffset.width==0) ? 0 : 0.5))
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    我使用 Timer 在动画持续时间(=0.5 秒)后更改索引,这解决了问题。而且不需要过渡。

    struct MyImagesView: View {
        @Binding var index:Int
        let imgArray:[URL]
        @Binding var dragOffset:CGSize
        @State var nextindex:Int = 1
        @State var screenSize:CGRect = UIScreen.main.bounds
        var body: some View {
            ZStack {
                MyImageView(array: imgArray, index: index-2).offset(x: -screenSize.width, y: 0)
                MyImageView(array: imgArray, index: index-1)
                MyImageView(array: imgArray, index: index).offset(x: screenSize.width, y: 0)
            }
            .offset(dragOffset)
            .onAppear(perform: { nextindex = index })
            .onChange(of: index, perform: { value in
                if dragOffset.width != 0 {
                    dragOffset = .zero
                }
            })
            .animation(.linear(duration: (dragOffset.width==0) ? 0 : 0.5))
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 2015-09-01
      • 2023-02-16
      • 2011-03-23
      • 1970-01-01
      相关资源
      最近更新 更多