iOS SwiftUI: отображать или отклонять вид программно
Я не мог найти упоминание о каких - либо способах сделать попы или отклонить программно моего представленного вида с SwiftUI.
Мне кажется, что единственный способ - это использовать уже интегрированное слайд-действие для модального окна (и что/как, если я хочу отключить эту функцию?) И кнопку возврата для стека навигации.
Кто-нибудь знает решение? Вы знаете, если это ошибка или она останется такой?
Ответы
Ответ 1
В этом примере используется новая среда var, задокументированная в примечаниях к выпуску Beta 5, в которой использовалось свойство value. Он был изменен в более поздней бета-версии для использования свойства wrappedValue. Этот пример сейчас актуален для версии GM. Эта та же самая концепция работает для отклонения модальных представлений, представленных с модификатором .sheet.
import SwiftUI
struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Button(
"Here is Detail View. Tap to go back.",
action: { self.presentationMode.wrappedValue.dismiss() }
)
}
}
struct RootView: View {
var body: some View {
VStack {
NavigationLink(destination: DetailView())
{ Text("I am Root. Tap for Detail View.") }
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
RootView()
}
}
}
Ответ 2
Теперь есть возможность программно вставлять в NavigationView, если хотите. Это бета-версия 5. Обратите внимание, что вам не нужна кнопка возврата. Вы можете программно вызвать свойство showSelf в DetailView любым удобным для вас способом. И вам не нужно отображать текст "Push" в мастере. Это может быть EmptyView(), что создает невидимый переход.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
MasterView()
}
}
}
struct MasterView: View {
@State var showDetail = false
var body: some View {
VStack {
NavigationLink(destination: DetailView(showSelf: $showDetail), isActive: $showDetail) {
Text("Push")
}
}
}
}
struct DetailView: View {
@Binding var showSelf: Bool
var body: some View {
Button(action: {
self.showSelf = false
}) {
Text("Pop")
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
Ответ 3
Вы можете попробовать использовать пользовательский вид и Transition
.
Здесь пользовательский модал.
struct ModalView<Content>: View where Content: View {
@Binding var isShowing: Bool
var content: () -> Content
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .center) {
if (!self.isShowing) {
self.content()
}
if (self.isShowing) {
self.content()
.disabled(true)
.blur(radius: 3)
VStack {
Text("Modal")
}
.frame(width: geometry.size.width / 2,
height: geometry.size.height / 5)
.background(Color.secondary.colorInvert())
.foregroundColor(Color.primary)
.cornerRadius(20)
.transition(.moveAndFade) // associated transition to the modal view
}
}
}
}
}
Я повторно использовал Transition.moveAndFade
из учебника " Анимационные представления и переходы".
Это определяется так:
extension AnyTransition {
static var moveAndFade: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
.combined(with: .opacity)
let removal = AnyTransition.scale()
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
Вы можете проверить это - в симуляторе, а не в превью - вот так:
struct ContentView: View {
@State var isShowingModal: Bool = false
func toggleModal() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
self.isShowingModal = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
self.isShowingModal = false
}
}
}
}
var body: some View {
ModalView(isShowing: $isShowingModal) {
NavigationView {
List(["1", "2", "3", "4", "5"].identified(by: \.self)) { row in
Text(row)
}.navigationBarTitle(Text("A List"), displayMode: .large)
}.onAppear { self.toggleModal() }
}
}
}
Благодаря этому переходу вы увидите, как модал sliding in from the trailing edge
, и он будет zoom and fade out when it is dismissed
.
Ответ 4
Основная концепция SwiftUI - следить за потоком данных.
Вы должны использовать переменную @State
и @State
значение этой переменной, чтобы контролировать выталкивание и удаление.
struct MyView: View {
@State
var showsUp = false
var body: some View {
Button(action: { self.showsUp.toggle() }) {
Text("Pop")
}
.presentation(
showsUp ? Modal(
Button(action: { self.showsUp.toggle() }) {
Text("Dismiss")
}
) : nil
)
}
}
Ответ 5
Я столкнулся с проблемой компиляции при попытке вызвать value
для привязки presentationMode. Изменение свойства на wrappedValue
исправило проблему для меня. Я предполагаю, что value
→ wrappedValue
- обновление языка. Я думаю, что это примечание было бы более уместным в качестве комментария к ответу Чака Н, но у меня недостаточно точек повторения, чтобы комментировать, я также предложил это изменение как и изменить, но мое изменение было отклонено как более подходящее в качестве комментария или ответа.