The SwiftUI ScrollView
lacks some options I would like and so I created a customized MyScrollView
primarily based on UIScrollView
wrapped inside a UIViewControllerRepresentable
. Whereas this works largely tremendous, the scrollbars are usually not positioned appropriately when .ignoreSaveArea()
is ready on the MyScrollView
. Is there one thing mistaken with my code or is that this some bug in SwiftUI? How can this be solved?
var physique: some View {
VStack {
Textual content("Some Header Content material")
MyScrollView {
VStack {
ForEach(0..<100, id: .self) { index in
Textual content("Line (index)")
.body(maxWidth: .infinity)
.background(.yellow)
}
}
}
.ignoresSafeArea()
}
}
On this setup, the scrollbar doesn’t finish on the high of the scrollview however a couple of pixels beneath. This isn’t the case when both Textual content("Some Header Content material")
or .ignoresSafeArea()
is eliminated. Nonetheless, I would like the header and the protected space ought to be ignored…
Is there one thing mistaken with how the UIScrollView
is used / positioned in my MyScrollView
? Is the overall implementation of MyScrollView
appropriate, or am I doing one thing mistaken?
struct MyScrollView: UIViewControllerRepresentable {
let content material: Content material
init(@ViewBuilder content material: () -> Content material) {
self.content material = content material()
}
func makeUIViewController(context: Context) -> UIViewController {
let scrollViewVC = UIViewController()
scrollViewVC.view.backgroundColor = .clear
let scrollView = UIScrollView()
scrollView.backgroundColor = .clear
let contentVC = UIHostingController(rootView: self.content material)
contentVC.view.backgroundColor = .clear
context.coordinator.contentVC = contentVC
context.coordinator.scrollView = scrollView
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollViewVC.view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: scrollViewVC.view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: scrollViewVC.view.bottomAnchor),
scrollView.leadingAnchor.constraint(equalTo: scrollViewVC.view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: scrollViewVC.view.trailingAnchor)
])
contentVC.willMove(toParent: scrollViewVC)
scrollViewVC.addChild(contentVC)
contentVC.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentVC.view)
NSLayoutConstraint.activate([
contentVC.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
contentVC.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
contentVC.view.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
contentVC.view.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
contentVC.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
contentVC.didMove(toParent: scrollViewVC)
return scrollViewVC
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
context.coordinator.contentVC?.rootView = content material
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
class Coordinator {
var contentVC: UIHostingController?
var scrollView: UIScrollView?
init() {
//...
}
}
}