Skip to content

Instantly share code, notes, and snippets.

@timothycosta
Created July 5, 2019 03:25
Show Gist options
  • Save timothycosta/0d8f64afeca0b6cc29665d87de0d94d2 to your computer and use it in GitHub Desktop.
Save timothycosta/0d8f64afeca0b6cc29665d87de0d94d2 to your computer and use it in GitHub Desktop.
UIScrollView wrapped for SwiftUI
//
// UIScrollViewWrapper.swift
// lingq-5
//
// Created by Timothy Costa on 2019/07/05.
// Copyright © 2019 timothycosta.com. All rights reserved.
//
import SwiftUI
struct UIScrollViewWrapper<Content: View>: UIViewControllerRepresentable {
var content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func makeUIViewController(context: Context) -> UIScrollViewViewController {
let vc = UIScrollViewViewController()
vc.hostingController.rootView = AnyView(self.content())
return vc
}
func updateUIViewController(_ viewController: UIScrollViewViewController, context: Context) {
viewController.hostingController.rootView = AnyView(self.content())
}
}
class UIScrollViewViewController: UIViewController {
lazy var scrollView: UIScrollView = {
let v = UIScrollView()
v.isPagingEnabled = true
return v
}()
var hostingController: UIHostingController<AnyView> = UIHostingController(rootView: AnyView(EmptyView()))
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.scrollView)
self.pinEdges(of: self.scrollView, to: self.view)
self.hostingController.willMove(toParent: self)
self.scrollView.addSubview(self.hostingController.view)
self.pinEdges(of: self.hostingController.view, to: self.scrollView)
self.hostingController.didMove(toParent: self)
}
func pinEdges(of viewA: UIView, to viewB: UIView) {
viewA.translatesAutoresizingMaskIntoConstraints = false
viewB.addConstraints([
viewA.leadingAnchor.constraint(equalTo: viewB.leadingAnchor),
viewA.trailingAnchor.constraint(equalTo: viewB.trailingAnchor),
viewA.topAnchor.constraint(equalTo: viewB.topAnchor),
viewA.bottomAnchor.constraint(equalTo: viewB.bottomAnchor),
])
}
}
@Flerex
Copy link

Flerex commented May 3, 2021

To anyone that might be using this and found that the subviews added appear on a white background: You just need to add the following line before returning in makeUIViewController:

vc.hostingController.view.backgroundColor = .clear

@rob5408
Copy link

rob5408 commented Jan 19, 2022

When using SwiftUI with tvOS, a ScrollView with a big Text View will not scroll. At least for me it didn't. I used this and added this v.panGestureRecognizer.allowedTouchTypes = [NSNumber(value: UITouch.TouchType.indirect.rawValue)] after let v = UIScrollView() and it started working. Many thanks!

@omarabubakrll
Copy link

omarabubakrll commented May 29, 2023

@timothycosta
I fixed the height gap issue for the full height by adjusting the spacing of the VStack to 0:

GeometryReader { proxy in UIScrollViewWrapper { VStack(spacing: 0) { // <--- here ForEach(0..<100, id: \.self) { obj in ZStack { Color.purple Text("\(obj)") } .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) } } .frame(width: proxy.size.width) .background(Color.blue.opacity(0.25)) } .ignoresSafeArea() }

@dz902
Copy link

dz902 commented Apr 13, 2024

Works great, just that if I put VStack in, VStack width is bound to its content and not greedy.

@mysterytoy
Copy link

I'm having the same issue with the content height. Anybody get it working?

@wilg Did you ever get this working?

@wilg
Copy link

wilg commented Apr 17, 2024

no, sorry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment