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()
}
}
}
}

发布于 2021-04-17 02:21:20
有几种方法可以获得视图的大小。在你的情况下,我假设你正在寻找屏幕大小。下面是实现这一点的方法。请记住,我没有打开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原始屏幕尺寸
var width = UIScreen.main.bounds.size.width
var height = UIScreen.main.bounds.size.height几何阅读器
这个更令人困惑,因为它会得到它所在的视图。它还有一个属性,您可以将其设置为忽略安全区域。如果您使用此方法,您将根据视图得到不同的响应。
//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()
}
}
}https://stackoverflow.com/questions/67129991
复制相似问题