gpt4 book ai didi

iOS 13 : Scroll view inside navigation controller won't go under the status bar

转载 作者:行者123 更新时间:2023-11-29 13:53:32 25 4
gpt4 key购买 nike

我想制作一个可在 SwiftUI 中使用的自定义 ScrollView ,它允许我设置滚动位置。我进行了一半,遇到了 ScrollView 在滚动时无法在状态栏下正确流动的问题。

问题是这样的:

enter image description here

在进行测试以查看问题所在时,我制作了一个基于 Storyboard的比较项目,该项目根本没有代码,只是一个与我在代码中的结构完全相同的结构。结果看起来像这样,这是我想要实现的:

enter image description here

似乎 Root View Controller View 没有一直到达顶部,但我不明白为什么。所有其他自动滚动插入魔术都可以正常工作。

这是我的代码,您可以在 Xcode 11 中使用 SwiftUI 创建一个新项目并将其粘贴到 ContentView.swift 中。

import SwiftUI
import UIKit

class UIScrollableViewController: UIViewController {
let scrollView = UIScrollView()
let contentController: UIViewController

init(contentController: UIViewController) {
self.contentController = contentController

super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(scrollView)

// Add child controller
scrollView.addSubview(contentController.view)
addChild(contentController)

let contentView = contentController.view!

// Constrain scroll view
scrollView.translatesAutoresizingMaskIntoConstraints = false;
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true

// Constrain child view to scroll view
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

// Constrain width of child view to width of self.view, NOT scroll view
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
}
}

class ScrollableNavigationController: UINavigationController, UINavigationBarDelegate {
}

struct ScrollableNavigationViewController<Content: View>: UIViewControllerRepresentable {
typealias UIViewControllerType = ScrollableNavigationController

let hostingController: UIHostingController<Content>
let scrollableContainer: UIScrollableViewController!

init(@ViewBuilder content: () -> Content) {
hostingController = UIHostingController(rootView: content())
scrollableContainer = UIScrollableViewController(contentController: hostingController)

scrollableContainer.title = "Scrollable"
}

func makeUIViewController(context: UIViewControllerRepresentableContext<ScrollableNavigationViewController>) -> ScrollableNavigationController {
let navigationController = ScrollableNavigationController(rootViewController: scrollableContainer)

navigationController.navigationBar.prefersLargeTitles = true

return navigationController
}

func updateUIViewController(_ navigationController: ScrollableNavigationController, context: UIViewControllerRepresentableContext<ScrollableNavigationViewController>) {
}
}

struct ScrollableNavigationView<Content: View>: View {
var content: Content

init(@ViewBuilder content: () -> Content) {
self.content = content()
}

var body: some View {
ScrollableNavigationViewController {
content
}
}
}

// MARK: Test

struct BoxView: View {
var colors: [Color] = [.red, .blue, .orange, .pink, .yellow]

var body: some View {
ForEach(0 ..< 20) { i in
ZStack {
Rectangle()
.fill(self.colors[i % 5])
.padding()
.frame(height: 130)
Text("\(i)")
.font(.title)
}
}
}
}

struct ContentView: View {
var body: some View {
ScrollableNavigationView {
BoxView()
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

最佳答案

问题似乎出在场景委托(delegate)上,它导致整个 View 层次结构被包裹在 UIHostingController 中,它具有嵌套的 SwiftUI Controller 似乎能够避免的嵌入魔法。为了证明这一点,我想出了一个稍微有点老套的解决方案。

替换这个:

window.rootViewController = UIHostingController(rootView: ContentView())

与:

window.rootViewController = MyHostingController(rootView: ContentView())

MyHostingController看起来像这样:

class MyHostingController<Content: View>: UIHostingController<Content> {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

view.subviews[0].frame = UIScreen.main.bounds
}
}

从 iOS 13.1 开始,您似乎真的应该只尝试在两层 UIKit 之间集成 SwiftUI,而不是相反。 SwiftUI 在其内部包含太多未记录的魔法。

关于iOS 13 : Scroll view inside navigation controller won't go under the status bar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58241095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com