有没有办法为新的全屏模式使用替代动画是 SwiftUI 中的 iOS 14?
目前它从底部向上滑动,但我想交叉溶解。我尝试了一些方法,但没有运气。我认为新的matchedGeometryEffect()
修饰符可能会有用。
以下是此新功能的默认用法
struct ContentView: View {
@State private var isShowing = false
var body: some View {
Button {
isShowing.toggle()
} label: {
Text("Show Modal").font(.largeTitle)
}.fullScreenCover(isPresented: $isShowing) {
Text("Hello").font(.largeTitle)
}
}
}
现在没有直接的 API 来执行此操作,但您可以使用 ZStack 进行简单的黑客操作来解决此问题
波纹管代码作为替代代码工作得很好
@State var isPresented = false
var body: some View {
ZStack {
NavigationView {
VStack {
Button(action: {
// trigger modal presentation
withAnimation {
self.isPresented.toggle()
}
}, label: {
Text("Show standard modal")
})
}.navigationBarTitle("Standard")
}
ZStack {
HStack {
Spacer()
VStack {
HStack {
Button(action: {
// trigger modal presentation
withAnimation {
self.isPresented.toggle()
}
}, label: {
Text("Dismiss")
.font(.headline)
.foregroundColor(.white)
})
Spacer()
Image(systemName: "xmark.circle.fill")
.foregroundColor(.white)
.onTapGesture {
withAnimation {
self.isPresented.toggle()
}
}
}
.padding(.top, UIApplication.shared.windows.filter{$0.isKeyWindow}.first?.safeAreaInsets.top)
Spacer()
}
Spacer()
}
}.background(Color.yellow)
.edgesIgnoringSafeArea(.all)
.offset(x: 0, y: self.isPresented ? 0 : UIApplication.shared.keyWindow?.frame.height ?? 0)
}
}
下面的代码工作,与匹配的几何效果((是你所追求的。
它现在被编码了,因为我还没有弄清楚如何从列表>详细信息传递数据。如果你这样做,请告诉我! ;)
import SwiftUI
struct Grid: View {
let namespace: Namespace.ID
var body: some View {
List{
Image("cover")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(4)
.padding()
.matchedGeometryEffect(id: "animation", in: namespace)
Image("cover2")
.resizable()
.frame(width: 50, height: 50)
.cornerRadius(4)
.padding()
.matchedGeometryEffect(id: "animation", in: namespace)
}
}
}
struct Detail: View {
let namespace: Namespace.ID
var body: some View {
Image("cover")
.resizable()
.aspectRatio(contentMode: .fit)
.cornerRadius(10)
.padding(40)
.matchedGeometryEffect(id: "animation", in: namespace)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(#colorLiteral(red: 0.234857142, green: 0.043259345, blue: 0.04711621255, alpha: 1)))
}
}
struct ContentView: View {
@Namespace private var ns
@State private var showDetails: Bool = false
var body: some View {
ZStack {
Spacer()
if showDetails {
Detail(namespace: ns)
}
else {
Grid(namespace: ns)
}
}
.onTapGesture {
withAnimation(.spring()) {
showDetails.toggle()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
所以要回答你的问题,让我们先深入研究问题。
您需要以与默认全屏封面不同的过渡来显示视图。如果是,那么这就是解决方案。
选项1:简单明了(初学者(
struct ContentView: View {
@State private var isShowing = false
var body: some View {
ZStack {
if(!isShowing) {
Button {
withAnimation {
isShowing.toggle()
}
} label: {
Text("Show Modal").font(.largeTitle)
}
} else {
VStack {
Text("Hello").font(.largeTitle)
Button(action: {
withAnimation {
isShowing.toggle()
}
}) {
Text("Go back")
}
}
.frame(width: 400, height: 900) //recommended - adjust this frame size according to you dynamically
.background(Color.red)
.transition(.slide) // you can use other transition like .move ,etc.
}
}
} }
选项 2:高级
将过渡添加到您的视图,并使此视图框架覆盖整个屏幕或要覆盖的部分。要了解有关过渡的更多信息,请查看此处 - https://stackoverflow.com/a/62767038 。您可以提出一个想法来创建自定义过渡。
将此自定义过渡添加到视图中,条件如下
struct ContentView: View { @State private var isShowing = false var body: some View { ZStack { if(!isShowing) { Button { withAnimation { isShowing.toggle() } } label: { Text("Show Modal").font(.largeTitle) } } else { VStack { Text("Hello").font(.largeTitle) Button(action: { withAnimation { isShowing.toggle() } }) { Text("Go back") } } .frame(width: 400, height: 900) //recommended - adjust this frame size according to you dynamically .background(Color.red) .transition(.rotate) //custom transition rotate from the link shared in 1st point. You can use inbuilt transition like .transition(.slide) and many more } } } }
在这里,我使用的是上面共享的链接中的自定义动画.rotate
,但您可以使用其他内置过渡或根据您的要求进行自定义过渡。