在 SwiftUI 中从侧面动画视图
Animate a view from the side in SwiftUI
说我有这样的看法:
struct CircleView: View {
var body: some View {
Circle()
}
}
换一种说法,我有这样的看法:
var body: some View {
GeometryReader { geo in
ZStack {
//some other views
if someState == .showCircle {
CircleView()
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
}
}
当 someState
变为 .showCircle
时,我想让 CircleView 从屏幕右侧动画到左半球可见的位置,所以它在屏幕的中间,并调暗 ZStack 中的其余内容。设置这种动画的最佳方法是什么?
您可以在圆上使用 .transition()
修饰符,在 不是 圆的其他视图上使用 .blur()
修饰符,结合 .animation()
.
此外,在“非圆形”的视图上,您需要添加另一个修饰符:.allowsHitTesting()
,以避免用户与模糊的视图进行交互。
请记住,当你触发someState
时,你必须使用.withAnimation()
闭包,否则圆圈不会滑入。
代码如下所示(我在 ZStack
上添加了一些内容只是为了提供示例)。为了方便起见,我还在示例中将 someState
变量设为布尔值,但在您的情况下,您只需检查枚举即可。
CircleView
struct CircleView: View {
@Binding var someState: Bool
var body: some View {
Circle()
.foregroundColor(.red)
.overlay(Text("All is blur"))
.onTapGesture {
someState.toggle()
}
// These modifiers are necessary to animate the circle
.transition(.move(edge: .trailing))
.animation(.easeInOut, value: someState)
}
}
另一种观点
@State private var someState = false
var body: some View {
GeometryReader { geo in
ZStack {
VStack {
Button {
// Without this closure, the circle does not slide in
withAnimation {
someState.toggle()
}
} label: {
Text("Show circle")
}
.padding()
Spacer()
Text("Bottom")
.padding()
}
// This modifier blurs the view that is not the circle
.blur(radius: someState ? 5 : 0)
// This modifier animates the blur effect
.animation(.easeInOut, value: someState)
// This is necessary to block the view from accepting user taps
// when the circle is showing
.allowsHitTesting(!someState)
if someState {
CircleView(someState: $someState)
// Stop the circle half-way
.offset(x: UIScreen.main.bounds.width / 2, y: 0)
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.ignoresSafeArea()
}
}
说我有这样的看法:
struct CircleView: View {
var body: some View {
Circle()
}
}
换一种说法,我有这样的看法:
var body: some View {
GeometryReader { geo in
ZStack {
//some other views
if someState == .showCircle {
CircleView()
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
}
}
当 someState
变为 .showCircle
时,我想让 CircleView 从屏幕右侧动画到左半球可见的位置,所以它在屏幕的中间,并调暗 ZStack 中的其余内容。设置这种动画的最佳方法是什么?
您可以在圆上使用 .transition()
修饰符,在 不是 圆的其他视图上使用 .blur()
修饰符,结合 .animation()
.
此外,在“非圆形”的视图上,您需要添加另一个修饰符:.allowsHitTesting()
,以避免用户与模糊的视图进行交互。
请记住,当你触发someState
时,你必须使用.withAnimation()
闭包,否则圆圈不会滑入。
代码如下所示(我在 ZStack
上添加了一些内容只是为了提供示例)。为了方便起见,我还在示例中将 someState
变量设为布尔值,但在您的情况下,您只需检查枚举即可。
CircleView
struct CircleView: View {
@Binding var someState: Bool
var body: some View {
Circle()
.foregroundColor(.red)
.overlay(Text("All is blur"))
.onTapGesture {
someState.toggle()
}
// These modifiers are necessary to animate the circle
.transition(.move(edge: .trailing))
.animation(.easeInOut, value: someState)
}
}
另一种观点
@State private var someState = false
var body: some View {
GeometryReader { geo in
ZStack {
VStack {
Button {
// Without this closure, the circle does not slide in
withAnimation {
someState.toggle()
}
} label: {
Text("Show circle")
}
.padding()
Spacer()
Text("Bottom")
.padding()
}
// This modifier blurs the view that is not the circle
.blur(radius: someState ? 5 : 0)
// This modifier animates the blur effect
.animation(.easeInOut, value: someState)
// This is necessary to block the view from accepting user taps
// when the circle is showing
.allowsHitTesting(!someState)
if someState {
CircleView(someState: $someState)
// Stop the circle half-way
.offset(x: UIScreen.main.bounds.width / 2, y: 0)
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.ignoresSafeArea()
}
}