UIScrollView jumpy view using UIHostingController

Viewed 274

I would like to put a SwiftUI view into UIScrollView using UIHostingController. However my button "toggle" seems to be jumping around the view during animation, even though I'm using auto layout to constrain the view.

The following video illustrates the problem of button text jumping during aniation

enter image description here import SwiftUI

struct ExpandableView: View {
    @State var expanded = false
    
    var body: some View {
        VStack {
            
            Button(action: { withAnimation {expanded.toggle() }}) {
                Text("toggle")
            }
            if expanded {
                Text("long text long text long text long text long text long text long text long text long text long text long textlong text long text long text long text long text long text long text long text long text long text long textlong text long text long text long text long text long text long text long text long text long text long text")
                    .font(.custom("x", fixedSize: 55))
            }
        }
    }
}


class ViewController: UIViewController {
    
    var scrollView: UIScrollView = {
        let sv = UIScrollView()
        sv.isDirectionalLockEnabled = true
        return sv
    }()
    
    var contentView: UIView = {
        let view = UIView()
        return view
    }()
    
    let controller = UIHostingController(rootView: ExpandableView())
    
    private var heightConstraint: NSLayoutConstraint?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        scrollView.frame = view.frame
        scrollView.contentSize = CGSize(width: view.bounds.size.width, height: view.bounds.size.height + 200)
        view.addSubview(scrollView)
        
        scrollView.addSubview(contentView)
        contentView.frame = scrollView.frame
        contentView.bounds = scrollView.bounds

        controller.view.backgroundColor = .yellow

        contentView.addSubview(controller.view)
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            controller.view.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor),
            controller.view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            controller.view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        ])
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        scrollView.contentSize = CGSize(width: view.bounds.width, height: 100 + controller.view.intrinsicContentSize.height)
    }
}
0 Answers
Related