SwiftUI布局教程:Stacks、Position和Offset详解

Viewed 0

SwiftUI教程(四)布局详解

本文将详细介绍SwiftUI中的布局方式。SwiftUI采用弹性布局,类似于HTML,没有传统坐标系的概念。我们主要使用Stacks(堆栈)进行视图的垂直、水平和深度排列,以及通过position和offset进行绝对和相对定位。

1. SwiftUI的布局

UI通常由多种视图组合而成,通过Stacks进行分组和布局。SwiftUI提供了三种堆栈:

  • HStack:水平排列子视图
  • VStack:垂直排列子视图
  • ZStack:根据深度排列子视图(从后到前)

此外,还有懒加载的LazyStack,以及绝对位置(position)和相对位置(offset)的使用。

2. Stacks的使用

垂直布局VStack

VStack用于垂直排列视图。可以指定对齐方式(如leading、trailing、center)和间距。

var body: some View {
    VStack(alignment: .leading, spacing: 20) {
        Text("orange").background(.orange).font(.caption)
        Text("red").background(.red).font(.title)
        Text("blue").background(.blue).font(.largeTitle)
        Text("yellow").background(.yellow).font(.callout)
    }
    .border(.gray)
}

默认情况下,VStack将视图居中对齐,但可以通过alignment属性更改。

水平布局HStack

HStack用于水平排列视图,语法与VStack类似。

HStack(alignment: .bottom, spacing: 20) {
    Text("orange").background(.orange).font(.caption)
    Text("red").background(.red).font(.title)
    Text("blue").background(.blue).font(.largeTitle)
    Text("yellow").background(.yellow).font(.callout)
}
.border(.gray)

深度布局ZStack

ZStack根据深度排列视图,可以指定对齐方式,但不能指定间距。

ZStack(alignment: .bottomTrailing) {
    Text("orange").background(.orange).font(.caption)
    Text("red").background(.red).font(.title)
    Text("blue").background(.blue).font(.largeTitle)
    Text("yellow").background(.yellow).font(.callout)
}
.border(.gray)

3. Stacks的混合使用

可以将VStack、HStack和ZStack组合使用以创建复杂布局。

HStack {
    ZStack {
        Circle()
            .fill(Color.yellow)
        Button(action: {
            print("button tapped")
        }) {
            Text("Press Me")
        }
    }
    .frame(width: 100.0, height: 100.0)
    VStack(alignment: .leading, spacing: 4) {
        Text("Beginning SwiftUI")
        Text("Greg Lim, 2021")
    }
}

这个例子中,ZStack和一个VStack嵌套在HStack中,ZStack包含一个圆和一个按钮,VStack包含两个文本视图。

4. LazyStack

LazyStack用于懒加载视图,通常与ScrollView和ForEach搭配使用,只加载当前显示的项。

ScrollView {
    LazyVStack {
        ForEach(1...100, id: \.self) {
            Text("Cell \($0)").padding()
        }
    }
}

使用LazyVStack可以提升性能,避免一次性加载所有数据。

5. ViewBuilder

Stacks的底层通过ViewBuilder实现,将子视图包装成一个视图返回。例如,VStack的定义包括buildBlock方法。

6. 绝对位置和相对位置

6.1 相对位置offset

offset用于相对偏移视图,不改变视图尺寸,只改变位置。可以传入CGSize或x、y坐标。

VStack(spacing: 50) {
    Text("Offset by passing CGSize()")
        .border(Color.green)
        .offset(CGSize(width: 20, height: 25))
        .border(Color.gray)

    Text("Offset by passing horizontal & vertical distance")
        .border(Color.green)
        .offset(x: 20, y: 50)
        .border(Color.gray)
}

偏移会将视图及其已有修饰符整体移动,而之后添加的修饰符(如border)则应用于偏移后的位置。

6.2 绝对位置position

position将视图的中心点放置到父视图的特定坐标上,会改变视图的布局。

Text("Position by passing a CGPoint()")
    .background(Color.blue)
    .position(CGPoint(x: 175, y: 100))
    .background(Color.green)

使用position后,视图的背景会充满整个父视图,因为位置是相对于父视图的。

通过掌握Stacks和位置调整,可以灵活布局SwiftUI视图,构建复杂的用户界面。

0 Answers