Skip to content

tevelee/SwiftUI-Flow

Repository files navigation

SwiftUI Flow Layout

Introduces HFlow and VFlow similar to HStack and VStack. Arranges views in lines and cuts new lines accordingly (if elements don't fit the bounding space).

HFlow

struct Colors: View {
    let colors: [Color] = [
        .blue,
        .orange,
        .green,
        .yellow,
        .brown,
        .mint,
        .indigo,
        .cyan,
        .gray,
        .pink
    ]

    var body: some View {
        HFlow {
            ForEach(colors, id: \.description) { color in
                RoundedRectangle(cornerRadius: 10)
                    .fill(color.gradient)
                    .frame(width: .random(in: 40...60), height: 50)
            }
        }
        .frame(maxWidth: 300)
    }
}

HFlow

VFlow

VFlow {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: 50, height: .random(in: 40...60))
    }
}
.frame(maxHeight: 300)

VFlow

Alignment

Supports the same alignments as HStack and VStack do.

HFlow(alignment: .top) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: 50, height: .random(in: 40...60))
    }
}
.frame(maxWidth: 300)

HFlow

Additionally, alignment can be specified on both axes. Ideal for tags.

HFlow(horizontalAlignment: .center, verticalAlignment: .top) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: .random(in: 30...60), height: 30)
    }
}
.frame(maxWidth: 300)

HFlow

Spacing

Customize spacing between rows and items separately.

HFlow(itemSpacing: 4, rowSpacing: 20) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: 50, height: 50)
    }
}
.frame(maxWidth: 300)

HFlow

Justified

Justify by stretching items, the spaces between them, or both.

HFlow(justification: .stretchItems) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(height: 50)
            .frame(minWidth: 35)
    }
}
.frame(width: 300)

HFlow


Distribute items evenly by minimizing the empty spaces left in each row. Implements the Knuth-Plass line breaking algorithm.

HFlow(distributeItemsEvenly: true) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: 65, height: 50)
    }
}
.frame(width: 300, alignment: .leading)

HFlow


Distribute and justify for visually pleasing UI.

HFlow(justification: .stretchItems, distributeItemsEvenly: true) {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(height: 50)
            .frame(minWidth: 60)
    }
}
.frame(width: 300)

HFlow

RTL

Adapts to left-to-right and right-to-left environments too.

HFlow {
    ForEach(colors, id: \.description) { color in
        RoundedRectangle(cornerRadius: 10)
            .fill(color.gradient)
            .frame(width: .random(in: 40...60), height: 50)
    }
}
.frame(maxWidth: 300)
.environment(\.layoutDirection, .rightToLeft)

HFlow