5
ScrollView(){
//no matter
}

Position is Top Left, but content will have smaller width than I needed

(2 strings in red rectangle must be single string, so need to enable both scrolls )

enter image description here


ScrollView([Axis.Set.horizontal, Axis.Set.vertical]) {
//no matter
}

In this case ScrollView's content have correct size for me.

But position of scrollView's content is centred ( both: horizontally and vertically )

How can I change default position to Top Left in case of ScrollView configured to both scrolls?

2

1 Answer 1

7
+200

Update: Xcode 13.4 / macOS 12.4

The issue is still there, but now the solution is simpler using ScrollViewReader:

struct TestTwoAxisScrollView: View {
    var body: some View {
        ScrollViewReader { sp in
            ScrollView([.horizontal, .vertical]) {
                VStack {
                    ForEach(0..<100) { _ in
                        self.row()
                    }
                }
                .border(Color.green)
                .id("root")
            }
            .border(Color.gray)
            .padding()
            .onAppear {
                sp.scrollTo("root", anchor: .topLeading)
            }
        }
    }

    func row() -> some View {
        Text(test)
            .border(Color.red) // uncomment to see border
    }
}

Original

Here is possible approach. Tested with Xcode 11.2 / macOS 10.15.3

Demo:

demo

Code (complete testable module, borders are added for better visibility of each component):

import SwiftUI

let test = """
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
"""

struct ScrollViewHelper: NSViewRepresentable {
    func makeNSView(context: NSViewRepresentableContext<ScrollViewHelper>) -> NSView {
        let view = NSView(frame: .zero)
        DispatchQueue.main.async { // << must be async, so view got into view hierarchy
            view.enclosingScrollView?.contentView.scroll(to: .zero)
            view.enclosingScrollView?.reflectScrolledClipView(view.enclosingScrollView!.contentView)
        }
        return view
    }

    func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<ScrollViewHelper>) {
    }
}

struct TestTwoAxisScrollView: View {
    var body: some View {
        ScrollView([.horizontal, .vertical]) {
            VStack {
                ForEach(0..<100) { _ in
                    self.row()
                }
            }
            .background(ScrollViewHelper()) // << active part !!
            .border(Color.green) // uncomment to see border
        }
        .border(Color.gray)
        .padding()
    }

    func row() -> some View {
        Text(test)
            .border(Color.red) // uncomment to see border
    }
}

struct TestTwoAxisScrollView_Previews: PreviewProvider {
    static var previews: some View {
        TestTwoAxisScrollView()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.