Created
July 7, 2023 17:11
-
-
Save noahsmartin/1b340c1e99ef077c54c2f798ec05f239 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
import SwiftUI | |
extension UIScrollView { | |
var visibleContentHeight: CGFloat { | |
frame.height - (adjustedContentInset.top + adjustedContentInset.bottom) | |
} | |
} | |
extension UIView { | |
var firstScrollView: UIScrollView? { | |
var subviews = subviews | |
while !subviews.isEmpty { | |
let subview = subviews.removeFirst() | |
subviews.append(contentsOf: subview.subviews) | |
if let scrollView = subview as? UIScrollView { | |
return scrollView | |
} | |
} | |
return nil | |
} | |
} | |
final class ExpandingViewController<Content: View>: UIHostingController<Content> { | |
private var hasModifiedHeight = false | |
private var didCall = false | |
var expansionSettled: (() -> Void)? | |
private func runCallback() { | |
guard !didCall else { return } | |
didCall = true | |
expansionSettled?() | |
} | |
override func viewDidLayoutSubviews() { | |
super.viewDidLayoutSubviews() | |
self.updateScrollViewHeight() | |
} | |
func updateScrollViewHeight() { | |
let scrollView = view.firstScrollView | |
if let scrollView { | |
let diff = scrollView.contentSize.height - scrollView.visibleContentHeight | |
if abs(diff) > 0.001 { | |
if hasModifiedHeight || diff > 0 { | |
hasModifiedHeight = true | |
view.frame = CGRect(x: view.frame.minX, y: view.frame.minY, width: view.frame.width, height: view.frame.height + diff) | |
} else { | |
runCallback() | |
} | |
} else { | |
runCallback() | |
} | |
} else { | |
runCallback() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment