[英]Present a new view in SwiftUI
我想單擊一個按鈕,然后在 UIKit 中以present modally
方式呈現一個新視圖
我已經看過“ 如何使用工作表呈現新視圖”,但我不想將其作為模式工作表附加到主視圖。
而且我不想使用NavigationLink
,因為我不希望新視圖和舊視圖有導航關系。
謝謝你的幫助...
您只需要一張能夠自行關閉的簡單sheet
:
struct ModalView: View {
@Binding var presentedAsModal: Bool
var body: some View {
Button("dismiss") { self.presentedAsModal = false }
}
}
並將其呈現為:
struct ContentView: View {
@State var presentingModal = false
var body: some View {
Button("Present") { self.presentingModal = true }
.sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
}
}
請注意,我將presentingModal
傳遞給模態,因此您可以將其從模態本身中消除,但您可以擺脫它。
fullscreen
(不僅僅是視覺上) 您需要訪問ViewController
。 所以你需要一些輔助容器和環境的東西:
struct ViewControllerHolder {
weak var value: UIViewController?
}
struct ViewControllerKey: EnvironmentKey {
static var defaultValue: ViewControllerHolder {
return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)
}
}
extension EnvironmentValues {
var viewController: UIViewController? {
get { return self[ViewControllerKey.self].value }
set { self[ViewControllerKey.self].value = newValue }
}
}
然后你應該使用實現這個擴展:
extension UIViewController {
func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
toPresent.modalPresentationStyle = style
toPresent.rootView = AnyView(
builder()
.environment(\.viewController, toPresent)
)
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "dismissModal"), object: nil, queue: nil) { [weak toPresent] _ in
toPresent?.dismiss(animated: true, completion: nil)
}
self.present(toPresent, animated: true, completion: nil)
}
}
你可以讓它fullscreen
像:
struct ContentView: View {
@Environment(\.viewController) private var viewControllerHolder: UIViewController?
var body: some View {
Button("Login") {
self.viewControllerHolder?.present(style: .fullScreen) {
Text("Main") // Or any other view you like
// uncomment and add the below button for dismissing the modal
// Button("Cancel") {
// NotificationCenter.default.post(name: Notification.Name(rawValue: "dismissModal"), object: nil)
// }
}
}
}
}
struct ContentView: View {
@State private var isPresented = false
var body: some View {
Button("Show Modal with full screen") {
self.isPresented.toggle()
}
.fullScreenCover(isPresented: $isPresented, content: FullScreenModalView.init)
}
}
struct FullScreenModalView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("This is a modal view")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.edgesIgnoringSafeArea(.all)
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
}
希望這個答案可以幫助到大家。 在下面評論您的結果。
參考: 此鏈接
免責聲明:下面並不是真正的“本機模式”,既不是行為也不是外觀和感覺,但如果有人需要一個視圖的自定義轉換,只激活頂部視圖,以下方法可能會有所幫助。
因此,如果您期望以下內容
這是演示方法的簡單代碼(可根據需要更改 animation 和轉換參數)
struct ModalView : View {
@Binding var activeModal: Bool
var body : some View {
VStack {
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
self.activeModal = false
}
}) {
Text("Hide modal")
}
Text("Modal View")
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.green)
}
}
struct MainView : View {
@Binding var activeModal: Bool
var body : some View {
VStack {
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
self.activeModal = true
}
}) {
Text("Show modal")
}
Text("Main View")
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.yellow)
}
}
struct ModalContainer: View {
@State var showingModal = false
var body: some View {
ZStack {
MainView(activeModal: $showingModal)
.allowsHitTesting(!showingModal)
.disabled(showingModal)
if showingModal {
ModalView(activeModal: $showingModal)
.transition(.move(edge: .bottom))
.zIndex(1)
}
}
}
}
這是一種簡單的方法——前瞻觀點。 這是非常直接的。
struct ChildView: View{
private let colors: [Color] = [.red, .yellow,.green,.white]
@Binding var index : Int
var body: some View {
let next = (self.index+1) % MyContainer.totalChildren
return ZStack{
colors[self.index % colors.count]
Button("myNextView \(next) ", action: {
withAnimation{
self.index = next
}
}
)}.transition(.asymmetric(insertion: .move(edge: .trailing) , removal: .move(edge: .leading) ))
}
}
struct MyContainer: View {
static var totalChildren = 10
@State private var value: Int = 0
var body: some View {
HStack{
ForEach(0..<(Self.totalChildren) ) { index in
Group{
if index == self.value {
ChildView(index: self.$value)
}}
}
}
}
}
然后在點擊按鈕時從 ContentView 呈現它:
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Button("Press to dismiss") {
dismiss()
}
.font(.title)
.padding()
.background(Color.black)
}
}
struct ContentView: View {
@State private var showingSheet = false
var body: some View {
Button("Show Sheet") {
showingSheet.toggle()
}
.sheet(isPresented: $showingSheet) {
SheetView()
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.