全屏覆盖/模态的替代动画 - iOS 14



有没有办法为新的全屏模式使用替代动画是 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:高级

  1. 将过渡添加到您的视图,并使此视图框架覆盖整个屏幕或要覆盖的部分。要了解有关过渡的更多信息,请查看此处 - https://stackoverflow.com/a/62767038 。您可以提出一个想法来创建自定义过渡。

  2. 将此自定义过渡添加到视图中,条件如下

    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,但您可以使用其他内置过渡或根据您的要求进行自定义过渡。

最新更新