微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI 如何获取自定义幻灯片转换的视图大小? 热点提示原始屏幕尺寸几何阅读器向后动画

如何解决SwiftUI 如何获取自定义幻灯片转换的视图大小? 热点提示原始屏幕尺寸几何阅读器向后动画

SwiftUI 具有认的幻灯片切换 .transition(.slide)。它工作得很好,但只有一半。我的意思是,我必须滑动我的视图,然后将它们向后滑动(我需要向后移动动画)。由于无法设置幻灯片过渡的方向,因此我实现了自定义过渡。实现很简单,效果很好。但是我无法获得视图大小来计算起点和终点偏移点。

extension AnyTransition {
    static func slide(direction: SlideModifier.Direction) -> AnyTransition {
        .asymmetric(insertion: .modifier(active: SlideModifier(positiveOffset: true,direction: direction),identity: SlideModifier(positiveOffset: nil,direction: direction)),removal: .modifier(active: SlideModifier(positiveOffset: false,direction: direction)))
    }
}

internal struct SlideModifier: ViewModifier {
    let positiveOffset: Bool?
    let direction: Direction
    let offsetSize: CGFloat = 200 // How can I get this value programmatically?
    
    enum Direction {
        case leading,top,trailing,bottom
    }
    
    func body(content: Content) -> some View {
        switch direction {
        case .leading:
            return content.offset(x: positiveOffset == nil ? 0 : (positiveOffset! ? offsetSize : -offsetSize))
        case .top:
            return content.offset(y: positiveOffset == nil ? 0 : (positiveOffset! ? offsetSize : -offsetSize))
        case .trailing:
            return content.offset(x: positiveOffset == nil ? 0 : (positiveOffset! ? -offsetSize : offsetSize))
        case .bottom:
            return content.offset(y: positiveOffset == nil ? 0 : (positiveOffset! ? -offsetSize : offsetSize))
        }
    }
}

我想定义等于视图大小的偏移大小。我的实验表明,这就是标准幻灯片过渡的工作方式。我尝试使用 GeometryReaderPreferenceKey获取大小。也许我做错了什么,但没有奏效。

这是一个使用我的自定义过渡的简单示例。

struct ContentView: View {
    @State private var isShowingRed = false

    var body: some View {
        ZStack {
            if isShowingRed {
                Color.red
                    .frame(width: 200,height: 200)
                    .transition(.slide(direction: .trailing))
            } else {
                Color.blue
                    .frame(width: 200,height: 200)
                    .transition(.slide(direction: .leading))
            }
        }
        .onTapGesture {
            withAnimation {
                isShowingRed.toggle()
            }
        }
    }
}

enter image description here

解决方法

有几种方法可以获取视图的大小。在您的情况下,我假设您正在寻找屏幕尺寸。这是获得它的方法。请记住,我没有打开 IDE 来对此进行全面测试,其中可能存在语法问题。稍后我会在 IDE 打开时更新我的​​答案。

热点提示

习惯使用内联条件,在 Swift UI 中处理动画和视图时会非常有帮助

someBool ? varIfTrue : varIfFalse
someValue == someTest ? varIfTrue : varIfFalse
//(boolCondition) ? (Value if True) : (Value If False)

//You can even chain them together,but be careful to keep it 
//organized if you do this.
someBool ? someBool2 ? val1 : val2 : someBool2 ? val3 : val4

原始屏幕尺寸

Nice Extension Provided Here

var width = UIScreen.main.bounds.size.width
var height = UIScreen.main.bounds.size.height

几何阅读器

这个有点令人困惑,因为它会获得它所在的 VIEW。它还有一个属性,您可以将其设置为忽略安全区域。如果您使用此方法,您将根据视图获得不同的响应。

//Parent Views Matter with GeometryReader
var body: some View {
    GeometryReader { geometry in 
        //Use the geometry,full screen size.
    }.ignoresSafeAreaAndEdges(.all)
}

var body: someView {
    VStack {
        GeometryReader { geometry in
             //This will have only the size of the parent view.
             // Ex: 100x100 square.
        }
    }.frame(width: 100,height: 100)
}

向后动画

你制作动画的方式是有效的,但是这样做会给你一个“倒带”类型的效果。

var body: some View {
    ZStack {
        if isShowingRed {
            Color.red
                .frame(width: 200,height: 200)
                .offset(isShowingRed ? 0 : 100)
                .animation(.spring()) //You can also use .default
        } else {
            Color.blue
                .frame(width: 200,height: 200)
                .offset(isShowingRed ? 100 : 0)
                .animation(.spring()) //You can also use .default

        }
    }
    .onTapGesture {
        withAnimation {
            isShowingRed.toggle()
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。