Specific arbitrary location of movable views in a ScrollView in SwiftUI (no auto-layout)

117 views Asked by At

I would like to have a scroll view with a lot of subviews that have a custom location and can be touch-moved around by the user. They might also have some other controls in them (including text fields or even text editors). I tried the following:

struct CardThing: Identifiable {
    let id: Int
    let position: CGPoint
    let label: String
}

let cards: [CardThing] = [
    CardThing(id: 1, position: CGPoint(x: 00, y: 10), label: "Card one"),
    CardThing(id: 2, position: CGPoint(x: 20, y: 20), label: "Card two"),
    CardThing(id: 3, position: CGPoint(x: 40, y: 40), label: "Card three"),
    CardThing(id: 4, position: CGPoint(x: 60, y: 60), label: "Card four"),
]

// The following view is a view of a graph structure.
//
struct ContentView: View {
    var body: some View {
        // The scroll view should be either virtually infinite
        // or some auto-resizable based on content with reasonable
        // margins. When margins are reached it is resized to maintain
        // those margins. But that is not relevant to this question.
        ScrollView {
            // The content will usually be in couple of dozens or couple of hundreds
            ForEach(cards) {
                // Here it will be some kind of a card view in the future
                Text($0.label)
                    // The position is explicit, should not undergo auto-layout
                    .position($0.position)
                    // Frames might also differ, should not undergo some auto-sizing
                    .frame(width: 320, height: 200)
                    .border(Color.green)
            }

            // The following will also be part of the view, but it is assumed
            // that the answer to the original question will answer it. It is just
            // here to provide more context about the idea of the view's content.

            // ForEach(links) { ... display link as touchable line-like shape ... }
        }
        .frame(width:600, height: 400)
    }
}

But the preview result looked automatically (mis-)aligned (also note the incomplete labels):

enter image description here

What I am doing wrong?

0

There are 0 answers