Joh*_*erg 8 ipad swift swiftui
如何使用 SwiftUI 在 iPad 上控制模态表的首选演示大小?我很惊讶在谷歌上找到答案是多么困难。
此外,通过向下拖动(取消)或实际执行自定义积极操作来了解模态是否被解除的最佳方法是什么?
ccw*_*den 10
以下是我在 iPad 上使用 SwiftUI 显示表单的解决方案:
struct MyView: View {
@State var show = false
var body: some View {
Button("Open Sheet") { self.show = true }
.formSheet(isPresented: $show) {
Text("Form Sheet Content")
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过此 UIViewControllerRepresentable 启用
class FormSheetWrapper<Content: View>: UIViewController, UIPopoverPresentationControllerDelegate {
var content: () -> Content
var onDismiss: (() -> Void)?
private var hostVC: UIHostingController<Content>?
required init?(coder: NSCoder) { fatalError("") }
init(content: @escaping () -> Content) {
self.content = content
super.init(nibName: nil, bundle: nil)
}
func show() {
guard hostVC == nil else { return }
let vc = UIHostingController(rootView: content())
vc.view.sizeToFit()
vc.preferredContentSize = vc.view.bounds.size
vc.modalPresentationStyle = .formSheet
vc.presentationController?.delegate = self
hostVC = vc
self.present(vc, animated: true, completion: nil)
}
func hide() {
guard let vc = self.hostVC, !vc.isBeingDismissed else { return }
dismiss(animated: true, completion: nil)
hostVC = nil
}
func presentationControllerWillDismiss(_ presentationController: UIPresentationController) {
hostVC = nil
self.onDismiss?()
}
}
struct FormSheet<Content: View> : UIViewControllerRepresentable {
@Binding var show: Bool
let content: () -> Content
func makeUIViewController(context: UIViewControllerRepresentableContext<FormSheet<Content>>) -> FormSheetWrapper<Content> {
let vc = FormSheetWrapper(content: content)
vc.onDismiss = { self.show = false }
return vc
}
func updateUIViewController(_ uiViewController: FormSheetWrapper<Content>,
context: UIViewControllerRepresentableContext<FormSheet<Content>>) {
if show {
uiViewController.show()
}
else {
uiViewController.hide()
}
}
}
extension View {
public func formSheet<Content: View>(isPresented: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content) -> some View {
self.background(FormSheet(show: isPresented,
content: content))
}
}
Run Code Online (Sandbox Code Playgroud)
您应该能够func show()根据 UIKit 规范修改代码,以便按照您喜欢的方式调整大小(如果需要,您甚至可以从 SwiftUI 端注入参数)。这就是我如何获取在 iPad 上使用的表单,因为它.sheet对于我的用例来说太大了
如果它对其他人有帮助,我可以通过依靠此代码来保持视图控制器来完成此工作: https://gist.github.com/timothycosta/a43dfe25f1d8a37c71341a1ebaf82213
struct ViewControllerHolder {
weak var value: UIViewController?
init(_ value: UIViewController?) {
self.value = value
}
}
struct ViewControllerKey: EnvironmentKey {
static var defaultValue: ViewControllerHolder? { ViewControllerHolder(UIApplication.shared.windows.first?.rootViewController) }
}
extension EnvironmentValues {
var viewController: ViewControllerHolder? {
get { self[ViewControllerKey.self] }
set { self[ViewControllerKey.self] = newValue }
}
}
extension UIViewController {
func present<Content: View>(
presentationStyle: UIModalPresentationStyle = .automatic,
transitionStyle _: UIModalTransitionStyle = .coverVertical,
animated: Bool = true,
completion: @escaping () -> Void = { /* nothing by default*/ },
@ViewBuilder builder: () -> Content
) {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
toPresent.modalPresentationStyle = presentationStyle
toPresent.rootView = AnyView(
builder()
.environment(\.viewController, ViewControllerHolder(toPresent))
)
if presentationStyle == .overCurrentContext {
toPresent.view.backgroundColor = .clear
}
present(toPresent, animated: animated, completion: completion)
}
}
Run Code Online (Sandbox Code Playgroud)
结合专门的视图来处理模式中的常见元素:
struct ModalContentView<Content>: View where Content: View {
// Use this function to provide the content to display and to bring up the modal.
// Currently only the 'formSheet' style has been tested but it should work with any
// modal presentation style from UIKit.
public static func present(_ content: Content, style: UIModalPresentationStyle = .formSheet) {
let modal = ModalContentView(content: content)
// Present ourselves
modal.viewController?.present(presentationStyle: style) {
modal.body
}
}
// Grab the view controller out of the environment.
@Environment(\.viewController) private var viewControllerHolder: ViewControllerHolder?
private var viewController: UIViewController? {
viewControllerHolder?.value
}
// The content to be displayed in the view.
private var content: Content
public var body: some View {
VStack {
/// Some specialized controls, like X button to close omitted...
self.content
}
}
Run Code Online (Sandbox Code Playgroud)
最后,只需调用:
ModalContentView.present( MyAwesomeView() )
MyAwesomeView在 .formSheet 模式内部显示。
| 归档时间: |
|
| 查看次数: |
2830 次 |
| 最近记录: |