У меня есть пользовательский UIViewControllerRepresentable
(код, связанный с макетом, показанный ниже). Он пытается реплицировать собственный SwiftUI ScrollView
, за исключением того, что он прокручивается снизу, за исключением верхнего.
Иерархия представления
view: UIView
|
\- scrollView: UIScrollView
|
\- innerView: UIView
|
\- hostingController.view: SwiftUI hosting view
Все это работает, как предполагалось, при инициализации представления. Представление хостинга заполняется его содержимым, и ограничения гарантируют, что представление прокрутки contentSize
установлено правильно.
Однако, когда изменяется содержимое представления хостинга, hostingController.view
не изменяет размерчтобы соответствовать его содержимому.
Зеленый: как и предполагалось, представление прокрутки соответствует размеру контроллера представления хоста.
Синий: вид самого хостинга. Он сохраняет размер, который имел при первой загрузке, и не тратит так, как следовало бы.
Красный: представление стека в представлении хостинга. На этом снимке экрана содержимое было добавлено в стек, что привело к его расширению. В результате вы увидите разницу в размере.
UIHostingController (синий) должен развернуться, чтобы соответствовать его содержимому (красный).
Размер содержимого представления прокрутки равен не явно установлен, потому что это обрабатывается автоматическим макетом.
Код ограничения показан ниже, если это помогает.
class UIBottomScrollViewController<Content: View>: UIViewController, UIScrollViewDelegate {
var hostingController: UIHostingController<Content>! = nil
init(rootView: Content) {
self.hostingController = UIHostingController<Content>(rootView: rootView)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var scrollView: UIScrollView = UIScrollView()
var innerView = UIView()
override func loadView() {
self.view = UIView()
self.addChild(hostingController)
view.addSubview(scrollView)
scrollView.addSubview(innerView)
innerView.addSubview(hostingController.view)
scrollView.delegate = self
scrollView.scrollsToTop = true
scrollView.isScrollEnabled = true
scrollView.clipsToBounds = false
scrollView.layoutMargins = .zero
scrollView.preservesSuperviewLayoutMargins = true
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
innerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
innerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
innerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
innerView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
innerView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
innerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
hostingController.view.topAnchor.constraint(equalTo: innerView.topAnchor).isActive = true
hostingController.view.leftAnchor.constraint(equalTo: innerView.leftAnchor).isActive = true
hostingController.view.rightAnchor.constraint(equalTo: innerView.rightAnchor).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: innerView.bottomAnchor).isActive = true
hostingController.view.autoresizingMask = []
hostingController.view.layoutMargins = .zero
hostingController.view.insetsLayoutMarginsFromSafeArea = false
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.autoresizingMask = []
scrollView.layoutMargins = .zero
scrollView.insetsLayoutMarginsFromSafeArea = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
innerView.autoresizingMask = []
innerView.layoutMargins = .zero
innerView.insetsLayoutMarginsFromSafeArea = false
innerView.translatesAutoresizingMaskIntoConstraints = false
hostingController.didMove(toParent: self)
scrollView.keyboardDismissMode = .interactive
}
}
struct BottomScrollView<Content: View>: UIViewControllerRepresentable {
var content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func makeUIViewController(context: Context) -> UIBottomScrollViewController<Content> {
let vc = UIBottomScrollViewController(rootView: self.content())
return vc
}
func updateUIViewController(_ viewController: UIBottomScrollViewController<Content>, context: Context) {
viewController.hostingController.rootView = self.content()
}
}