banner
wangqiyang

wangqiyang

SwiftUI 入门:布局基础

基础布局容器#

Stack#

在 SwiftUI 中,Stack  是一种基本的视图容器,可以用来排列和布局其他视图。
在  Stack  中,所有的子视图都是在一个水平或垂直方向上排列的,你可以使用  HStack  创建水平方向的  Stack,使用  VStack  创建垂直方向的  Stack,或者使用  ZStack  创建一个带有层次关系的  Stack

VStack#

在 SwiftUI 中,VStack  是一种基本的视图容器,用于在垂直方向上排列其他视图。
VStack  可以包含任意数量的子视图(其实是有上限的,但可以通过 Group 规避这个限制),这些子视图将按照从上到下的顺序排列。

以下是一个简单的  VStack  示例:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("First")
            Text("Second")
            Text("Third")
        }
    }
}

在这个示例中,VStack  包含了三个  Text  视图,它们被按照从上到下的顺序排列。

除了基本的布局外,VStack  还支持许多其他的选项和修饰符,以帮助你自定义视图的外观和行为。
以下是一些常用的选项和修饰符:

  • alignment:用于指定子视图在垂直方向上的对齐方式。默认情况下,子视图将在垂直中心对齐,但你可以使用  alignment  选项来指定其他的对齐方式,例如  .leading.trailing.top.bottom  等等。
  • spacing:用于指定子视图之间的间距。默认情况下,子视图之间没有间距,但你可以使用  spacing  选项来添加间距,例如  VStack(spacing: 10)  将在每个子视图之间添加 10 个点的间距。
  • padding:用于指定  VStack  的内边距。默认情况下,VStack  没有内边距,但你可以使用  padding  选项来添加内边距,例如  VStack().padding(10)  将在  VStack  外部添加 10 个点的内边距。

需要注意的是,当你在  VStack  中包含多个视图时,它们的大小和位置可能会受到其他视图的影响。为了避免这种情况,你可以使用  Spacer  视图来占用额外的空间,或者使用  GeometryReader  来获取父视图的大小,并根据需要对子视图进行调整。

HStack#

和 VStack 相似,差异仅仅表现在方向上。
以下是一个简单的  HStack  示例:

struct ContentView: View {
    var body: some View {
        HStack {
            Text("First")
            Text("Second")
            Text("Third")
        }
    }
}

在这个示例中,HStack  包含了三个  Text  视图,它们被按照从左到右的顺序排列。

HStack 常用的选项和修饰符和 VStack 类似:

  • alignment:用于指定子视图在水平方向上的对齐方式。默认情况下,子视图将在水平中心对齐,但你可以使用  alignment  选项来指定其他的对齐方式,例如  .leading.trailing.top.bottom  等等。
  • spacing:用于指定子视图之间的间距。默认情况下,子视图之间没有间距,但你可以使用  spacing  选项来添加间距,例如  HStack(spacing: 10)  将在每个子视图之间添加 10 个点的间距。
  • padding:用于指定  HStack  的内边距。默认情况下,HStack  没有内边距,但你可以使用  padding  选项来添加内边距,例如  HStack().padding(10)  将在  HStack  外部添加 10 个点的内边距。

ZStack#

在 SwiftUI 中,ZStack  是一种基本的视图容器,用于在垂直方向上堆叠其他视图。ZStack  可以包含任意数量的子视图,这些子视图将按照从前到后的顺序堆叠,类似于图层。以下是一个简单的  ZStack  示例:

struct ContentView: View {
    var body: some View {
        ZStack {
            Image("background")
            Text("Hello, World!")
        }
    }
}

在这个示例中,ZStack  包含了一个  Image  视图和一个  Text  视图,它们被堆叠在一起。由于  Text  视图在  Image  视图的前面,因此它会显示在最上面。

除了基本的堆叠外,ZStack  还支持许多其他的选项和修饰符,以帮助你自定义视图的外观和行为。以下是一些常用的选项和修饰符:

  • alignment:用于指定子视图在垂直方向上的对齐方式。默认情况下,子视图将在垂直中心对齐,但你可以使用  alignment  选项来指定其他的对齐方式,例如  .leading.trailing.top.bottom  等等。
  • background:用于指定  ZStack  的背景视图。默认情况下,ZStack  没有背景视图,但你可以使用  background  选项来添加背景视图,例如  ZStack().background(Color.blue)  将在  ZStack  后面添加一个蓝色的背景。
  • overlay:用于在  ZStack  上添加覆盖视图。默认情况下,ZStack  没有覆盖视图,但你可以使用  overlay  选项来添加覆盖视图,例如  ZStack().overlay(Text("Overlay"))  将在  ZStack  上方添加一个覆盖视图。

需要注意的是,当你在  ZStack  中包含多个视图时,它们的大小和位置可能会受到其他视图的影响。为了避免这种情况,你可以使用  Spacer  视图来占用额外的空间,或者使用  GeometryReader  来获取父视图的大小,并根据需要对子视图进行调整。

LazyVStack#

LazyVStack 是 SwiftUI 中用于垂直布局的一种视图。LazyVStack 类似于 VStack,但具有更高的性能和更少的内存使用,因为它仅在需要时才加载和显示其子视图。LazyVStack 通常用于显示大量的子视图,如列表和网格。

以下是创建 LazyVStack 的基本语法:

LazyVStack(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, pinnedViews: PinnedScrollableViews = .init(), @ViewBuilder content: () -> Content)

其中,alignment参数用于指定子视图在垂直轴上的对齐方式(如.top.center.bottom等),spacing参数用于指定子视图之间的间距,pinnedViews参数用于指定要固定在ScrollView顶部或底部的视图,content参数是一个闭包,用于返回要在LazyVStack中显示的内容。

例如,下面的代码创建了一个简单的LazyVStack,其中包含 10 个文本视图:

LazyVStack {
    ForEach(1...10, id: \.self) { index in
        Text("Item \(index)")
    }
}

在这个例子中,我们使用ForEach循环来创建 10 个文本视图,并将它们添加到LazyVStack中。由于LazyVStack是 “惰性” 的,它只会在需要时动态加载和显示每个文本视图,这可以提高性能并减少内存使用。

LazyHStack#

LazyHStack  是 SwiftUI 中的一个视图容器,用于在水平方向上排列一组视图。与  HStack  不同的是,LazyHStack  会在需要时才实例化它的子视图,这可以提高性能并减少内存使用量。

以下是  LazyHStack  的一些常见用法:

  1. 排列一组视图:当你需要在水平方向上排列一组视图时,可以使用  LazyHStack  来将它们放置在一个容器中。这使得可以更轻松地布局视图,并在需要时进行懒加载,从而提高性能和内存使用效率。

举个例子,如果你需要在一个视图中排列一组按钮,可以使用  LazyHStack  来将它们放置在一个水平容器中,并在需要时进行懒加载。

LazyHStack {
    Button("Button 1") {
        // do something
    }
    Button("Button 2") {
        // do something
    }
    Button("Button 3") {
        // do something
    }
}
  1. 支持大量视图的布局:当你需要在一个视图中放置大量视图时,可以使用  LazyHStack  来进行懒加载,从而提高性能和内存使用效率。这对于需要展示大量数据的应用程序非常有用,如社交媒体应用程序、新闻应用程序等。

举个例子,如果你需要在一个视图中显示一组图片,可以使用  LazyHStack  来将它们放置在一个水平容器中,并在需要时进行懒加载。

LazyHStack {
    ForEach(0..<100) { index in
        Image("image\(index)")
            .resizable()
            .frame(width: 50, height: 50)
    }
}

总之,LazyHStack  可以帮助你在 SwiftUI 中更轻松地布局和管理视图,并提高性能和内存使用效率。如果你需要在水平方向上排列一组视图,并且希望在需要时进行懒加载,那么  LazyHStack  是一个非常实用的视图容器。

Grid#

在 SwiftUI 中,可以使用  LazyVGridLazyHGrid  和  LazyVGrid  三种视图容器来创建网格布局。这些容器提供了一种方便的方式来排列和布局许多视图,可以让你轻松地创建表格、照片墙、电影海报和其他复杂的布局。

以下是一些 SwiftUI 中使用网格布局的常见方法和示例:

LazyVGrid#

垂直网格布局:可以使用  LazyVGrid  容器来创建垂直方向上的网格布局。在  LazyVGrid  中,你可以指定列数、行之间的间距和单元格之间的间距。

struct ContentView: View {
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]

    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 16) {
                ForEach(0 ..< 10) { index in
                    Text("Item \(index)")
                        .frame(height: 100)
                }
            }
            .padding()
        }
    }
}

LazyHGrid#

水平网格布局:可以使用  LazyHGrid  容器来创建水平方向上的网格布局。在  LazyHGrid  中,你可以指定行数、列之间的间距和单元格之间的间距。

struct ContentView: View {
    let rows = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]

    var body: some View {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows, spacing: 16) {
                ForEach(0 ..< 10) { index in
                    Text("Item \(index)")
                        .frame(width: 200, height: 100)
                }
            }
            .padding()
        }
    }
}

LazyGrid#

自定义网格布局:可以使用  LazyGrid  容器来创建自定义网格布局。在  LazyGrid  中,你可以指定行数、列数、行之间的间距和列之间的间距,并自定义每个单元格的大小和位置。

struct ContentView: View {
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]

    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 16) {
                ForEach(0 ..< 10) { index in
                    Text("Item \(index)")
                        .frame(height: CGFloat.random(in: 50...200))
                        .background(Color.blue)
                        .cornerRadius(8)
                        .overlay(
                            Text("\(index)")
                                .foregroundColor(.white)
                        )
                }
            }
            .padding()
        }
    }
}

ScrollView#

基本用法#

ScrollView 是 SwiftUI 中用于显示可滚动内容的一种视图。ScrollView 可以垂直或水平滚动,并支持滚动手势和滚动条。ScrollView 可以用于显示各种类型的内容,如文本、图像、列表等等。

以下是创建 ScrollView 的基本语法:

struct ContentView: View {
    var body: some View {
        ScrollView {
            VStack {
                ForEach(0..<50) { index in
                    Text("Row \(index)")
                }
            }
        }
    }
}

在 ScrollView 中,我们可以添加任意数量的视图,包括文本视图、图像视图、列表视图等等。ScrollView 会自动将这些视图包裹在一个可滚动的容器中,并根据内容自动调整它们的大小和位置。

例如,下面的代码创建了一个简单的 ScrollView,其中包含一个文本视图:

ScrollView {
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel ante ac lorem bibendum semper. Nulla facilisi. Sed quis risus nec risus bibendum tempus. Nam luctus hendrerit eros, a tempor augue pharetra vel. Donec at risus vitae velit malesuada egestas.")
}

在这个例子中,ScrollView 会自动将文本视图包裹在一个可滚动的容器中,并根据文本的长度自动调整其大小和位置。用户可以通过手势滚动文本视图,或使用滚动条控制滚动位置。

常用修饰符#

以下是 ScrollView 的一些常用修饰符:

  1. scrollIndicatorInsets(_ :): 用于设置滚动指示器的边距。这个修饰符接受一个 EdgeInsets 类型的参数,用于指定顶部、底部、左侧和右侧的边距。
  2. showsIndicators(_ :): 用于控制是否显示滚动指示器。这个修饰符接受一个布尔值类型的参数,默认值为 true,表示显示滚动指示器。如果将其设置为 false,则不会显示滚动指示器。
  3. onOffsetChange(_ :): 用于在 ScrollView 滚动时执行自定义操作。这个修饰符接受一个闭包类型的参数,其中包含当前偏移量的值。可以使用这个修饰符来实现自定义滚动行为,例如在滚动到特定位置时执行某些操作。
  4. contentInsets(_ :): 用于设置 ScrollView 内容的边距。这个修饰符接受一个 EdgeInsets 类型的参数,用于指定顶部、底部、左侧和右侧的边距。
  5. contentOffset(_ :): 用于设置 ScrollView 的初始偏移量。这个修饰符接受一个 CGPoint 类型的参数,用于指定 ScrollView 的初始偏移量。
  6. background(_ :): 用于设置 ScrollView 的背景。这个修饰符接受一个 View 类型的参数,用于指定 ScrollView 的背景视图。
  7. overlay(_ :): 用于在 ScrollView 上添加覆盖视图。这个修饰符接受一个 View 类型的参数,用于指定要添加到 ScrollView 上的覆盖视图。
  8. ignoresSafeArea(_ edges: Edge.Set): 用于控制 ScrollView 是否忽略安全区域。这个修饰符接受一个 Edge.Set 类型的参数,用于指定要忽略的安全区域边缘。
  9. content(_ :): 用于指定 ScrollView 的内容视图。这个修饰符接受一个 View 类型的参数,用于指定 ScrollView 的内容视图。

Spacer#

Spacer  是 SwiftUI 中的一个视图修饰符,用于在视图中创建一个占位符,以便在布局过程中占用空间。当你使用  Spacer  时,它会自动填充剩余的可用空间,从而将视图推动到视图容器的边缘。

以下是  Spacer  的一些常见用法:

  1. 在  VStack  或  HStack  中使用  Spacer:当你将  Spacer  放置在  VStack  或  HStack  中时,它会自动将其前面的视图推到容器的顶部或左侧,并将其后面的视图推到容器的底部或右侧。这使得可以在容器中创建自适应的布局。

举个例子,如果你想在  VStack  中创建一个具有固定高度的标题和一个自适应高度的文本视图,你可以在它们之间添加一个  Spacer。这将会使文本视图自动填充剩余的可用空间,从而将其推到容器的底部。

VStack {
    Text("Title")
        .font(.largeTitle)
        .frame(height: 100)
    Spacer()
    Text("This is a long text that should wrap over several lines and fill the remaining space in the container.")
}
  1. 在  ZStack  中使用  Spacer:当你将  Spacer  放置在  ZStack  中时,它会将其前面的视图推到前面,将其后面的视图推到后面,并自动占用剩余的可用空间。这使得可以在  ZStack  中创建自适应的布局。

举个例子,如果你想在  ZStack  中创建一个具有固定大小的圆形图像和一个自适应大小的矩形视图,你可以在它们之间添加一个  Spacer。这将会使矩形视图自动填充剩余的可用空间,从而将其推到圆形图像的周围。

ZStack {
    Circle()
        .fill(Color.blue)
        .frame(width: 100, height: 100)
    Spacer()
    Rectangle()
        .fill(Color.red)
        .frame(maxWidth: .infinity, maxHeight: .infinity)
}

总之,Spacer  可以帮助你在 SwiftUI 中创建自适应布局,使得视图可以自动填充剩余的可用空间,从而实现更加灵活和动态的布局效果。

Group#

GGroup  是 SwiftUI 中的一个容器视图,用于将多个视图组合在一起,并对它们进行分组。它不会在视图层次结构中创建任何新的视图层次关系,而只是将其内部的视图作为一组视图进行处理。

以下是  Group  的一些常见用法:

  1. 将多个视图组合在一起:当你需要将多个视图组合在一起时,可以使用  Group  来将它们包装在一个容器中。这使得可以在代码中更好地组织视图,并使其更易于阅读和维护。

举个例子,如果你需要在一个视图中显示多个按钮,可以将这些按钮放在一个  Group  中,这样它们就可以作为一个整体处理,并可以在需要时轻松地进行样式和布局更改。

Group {
    Button("Button 1") {
        // do something
    }
    Button("Button 2") {
        // do something
    }
    Button("Button 3") {
        // do something
    }
}
  1. 对视图进行分组:当你需要对视图进行分组时,可以使用  Group  来将它们包装在一个容器中。这使得可以轻松地将相似的视图组织在一起,并将其作为一个整体进行处理。

举个例子,如果你需要在一个视图中显示多个文本标签,可以将它们分组在一个  Group  中,并为该组添加样式和布局属性。这样可以更好地组织代码,并使其更易于维护。

Group {
    Text("Label 1")
    Text("Label 2")
    Text("Label 3")
}
.font(.largeTitle)
.padding()

总之,Group  可以帮助你在 SwiftUI 中更好地组织和管理视图,并使其更易于阅读和维护。它是一个非常简单但实用的容器视图,可以使代码更加简洁和可读。

嵌套布局#

在 SwiftUI 中,可以通过嵌套一个视图容器来创建复杂的布局。这允许你使用多个容器,每个容器都负责管理一组视图。这样可以更轻松地组合和布局视图,并在需要时进行懒加载,以提高性能和内存使用效率。

以下是一些 SwiftUI 中常用的嵌套布局的示例:

  1. 垂直和水平布局的组合:可以使用  VStack  和  HStack  的组合来实现垂直和水平布局的混合。这对于需要在水平和垂直方向上排列视图的应用程序非常有用,如表单、工具栏等。
VStack {
    HStack {
        Text("First")
        Text("Second")
    }
    HStack {
        Text("Third")
        Text("Fourth")
    }
}
  1. 嵌套的列表:可以将列表视图嵌套在另一个列表或视图容器中,以创建更复杂的布局。这对于需要显示层次结构数据的应用程序非常有用,如目录、导航等。
List {
    Section(header: Text("Section 1")) {
        Text("Item 1")
        Text("Item 2")
    }
    Section(header: Text("Section 2")) {
        List {
            Text("Nested Item 1")
            Text("Nested Item 2")
        }
    }
}
  1. 嵌套的滚动视图:可以将滚动视图嵌套在另一个滚动视图或视图容器中,以创建更复杂的滚动布局。这对于需要显示大量数据的应用程序非常有用,如新闻、社交媒体等。
ScrollView {
    VStack {
        Image("header-image")
            .resizable()
            .frame(height: 200)
        VStack {
            Text("Title")
                .font(.largeTitle)
            Text("Subtitle")
                .font(.headline)
                .foregroundColor(.gray)
            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, ligula id gravida rutrum, sem urna volutpat purus, sit amet suscipit ex odio vel arcu. Nulla cursus sollicitudin massa. Etiam quis ex at odio eleifend mollis. Fusce accumsan turpis ac ipsum ultrices, nec lobortis dolor consectetur. Donec sit amet bibendum mi, id vestibulum justo. Sed eget dictum orci. Donec vitae quam ut eros rhoncus faucibus.")
                .font(.body)
        }
    }
}

布局修饰符#

在 SwiftUI 中,布局修饰符可以用于在视图周围添加内边距、背景、覆盖图像等。以下是常用的布局修饰符:

  1. padding(_:):在视图周围添加内边距。例如,Text("Hello World").padding()  将在  Text  视图周围添加默认内边距。
  2. background(_:):为视图添加背景。例如,Text("Hello World").background(Color.blue)  将为  Text  视图添加蓝色背景。
  3. border(_:width:):为视图添加边框。例如,Text("Hello World").border(Color.gray, width: 1)  将为  Text  视图添加灰色边框,宽度为 1。
  4. cornerRadius(_:):为视图添加圆角。例如,Text("Hello World").cornerRadius(10)  将为  Text  视图添加 10 个点的圆角。
  5. shadow(_:):为视图添加阴影。例如,Text("Hello World").shadow(color: .gray, radius: 2)  将为  Text  视图添加灰色阴影,半径为 2。
  6. overlay(_:):在视图上方添加覆盖图像。例如,Text("Hello World").overlay(Image(systemName: "star"))  将在  Text  视图上方添加一个星形图像。
  7. frame(width:height:alignment:):为视图指定框架大小和对齐方式。例如,Text("Hello World").frame(width: 100, height: 50, alignment: .center)  将为  Text  视图指定一个宽度为 100、高度为 50、水平和垂直居中对齐的框架。
  8. aspectRatio(_:contentMode:):为视图指定宽高比和内容模式。例如,Image("photo").aspectRatio(1.5, contentMode: .fit)  将为  Image  视图指定一个宽高比为 1.5,并将图像内容缩放以适应视图大小。
  9. alignmentGuide(_:computeValue:):允许你定义自定义的对齐指南,以便在布局中使用。这个修饰符接受两个参数:一个对齐标识符和一个计算函数。例如,VStack(alignment: .leading) { ... }.alignmentGuide(.leading) { d in d[.trailing] }  可以将  .leading  对齐指南的位置设置为其子视图的  .trailing
  10. fixedSize():指定视图的大小为其内容大小。例如,Text("Hello World").fixedSize()  将为  Text  视图指定一个大小,该大小等于  Text  视图内容的大小。
  11. layoutPriority(_:):指定视图的布局优先级。布局优先级用于确定哪个视图将优先布局。例如,VStack { Text("Hello").layoutPriority(1); Text("World").layoutPriority(2) }  将确保  Text("World")  视图具有更高的布局优先级,并且将优先布局。
  12. offset(_:):在视图的位置上添加偏移量。例如,Text("Hello World").offset(x: 10, y: 20)  将在  Text  视图的位置上添加 x 轴偏移量为 10,y 轴偏移量为 20。
  13. rotationEffect(_:anchor:):为视图添加旋转效果。例如,Text("Hello World").rotationEffect(.degrees(45))  将为  Text  视图添加 45 度的旋转效果。
  14. scaleEffect(_:anchor:):为视图添加缩放效果。例如,Text("Hello World").scaleEffect(2)  将为  Text  视图添加两倍大小的缩放效果。
  15. clipped():将视图修剪为其父视图的边界框内。例如,Image("photo").clipped()  将将图像修剪为其父视图的边界框内。

布局优先级#

在 SwiftUI 中,布局优先级用于决定视图在布局中的相对位置。布局优先级越高的视图将在布局时优先考虑,并优先分配可用空间。如果所有视图的布局优先级相同,则它们将平均分配可用空间。

你可以使用  layoutPriority(_:)  修饰符为视图设置布局优先级。这个修饰符接受一个浮点数值作为参数,表示视图的布局优先级。默认情况下,所有视图的布局优先级都是 0。

例如,你可以使用以下代码为两个文本视图设置布局优先级:

VStack {
    Text("First").layoutPriority(1)
    Text("Second").layoutPriority(2)
}

在上面的代码中,第二个文本视图具有更高的布局优先级,因此它将首先分配可用的空间。如果它需要更多的空间,它将优先考虑并尽可能多地分配可用的空间。而第一个文本视图的布局优先级较低,因此它将尽可能少地分配可用的空间。

需要注意的是,布局优先级只能用于决定子视图在父视图中的相对位置,而不能用于决定子视图在屏幕中的绝对位置。如果你想要更精细的布局控制,可以考虑使用其他布局修饰符,如  framepaddingoffset  等。

自动布局#

在 SwiftUI 中,自动布局是通过使用一种称为 “声明式布局” 的方法来实现的。这种方法允许你通过声明视图的期望行为,而不是直接操作布局,来控制视图的布局。这种方法非常类似于使用 HTML 和 CSS 创建 Web 页面的方式。

SwiftUI 中的自动布局是基于一组内置的布局系统,包括  VStackHStackZStackListScrollView  等。这些布局系统可以嵌套使用,并且可以通过添加修饰符来自定义它们的行为。

例如,以下代码使用  VStack  和  HStack  来创建一个简单的布局:

VStack {
    HStack {
        Text("Hello")
        Text("World")
    }
    Text("How are you?")
}

在上面的代码中,VStack  和  HStack  分别表示垂直和水平方向的布局,因此它们可以嵌套使用来创建更复杂的布局。在这个例子中,HStack  包含两个文本视图,这两个文本视图在水平方向上并排排列。VStack  包含一个  HStack  和一个文本视图,这些视图在垂直方向上排列。因此,整个布局包含三个文本视图,其中两个在水平方向上并排排列,而第三个在垂直方向上排列。

需要注意的是,SwiftUI 中的自动布局是响应式的,这意味着视图将根据其内容和环境自动调整大小和位置。例如,当设备的屏幕方向发生变化时,视图的布局将自动更新以适应新的方向。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。