【发布时间】:2021-04-16 17:50:52
【问题描述】:
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), identity: SlideModifier(positiveOffset: nil, 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))
}
}
}
我想定义等于视图大小的偏移大小。我的实验表明,这就是标准幻灯片过渡的工作方式。我尝试使用GeometryReader 和PreferenceKey 来获取大小。也许我做错了什么,但没有奏效。
这是一个使用我的自定义过渡的简单示例。
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()
}
}
}
}
【问题讨论】:
-
UIScreen.main.bounds.someProperty将在没有 GeometryReader 的情况下为您提供屏幕尺寸。此外,您应该能够通过执行View().offset(x: isOffScreen == true ? UIScreen.main.bounds.size.width / 2 : 0)之类的操作来设置偏移量然后当您更改isOffScreen时将其包装在withAnimation { isOffScreen.toggle() } -
@laenhall:您尝试解决问题的方式是错误的!您不需要在每个动画中读取大小,这是对 cpu 的滥用,您只需要在午餐时读取一次并在每次方向更改时更新
-
@xTwisteDx 如果我使用
UIScreen.main.bounds,动画对象将在整个屏幕上移动。这种行为并不总是可以接受的。 -
@swiftPunk 你有什么建议吗?
标签: view swiftui size transition direction