iOSSwiftUI Stack

Posted hzy1721

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOSSwiftUI Stack相关的知识,希望对你有一定的参考价值。

Stack

Stack 可以把多个视图按照简单的规则组合为一个复合视图,按照组合的方向可以分为水平 (HStack)、垂直 (VStack)、竖直 (ZStack)。

不提供任何构造方法的参数时,Stack 默认居中对齐子视图,并在视图之间加入少量间隔。

可以使用 Stack 的 View modifier、Spacer、Divider 来更精细地定制 Stack 中的布局。

比如用三种 Stack 写一个个人信息的复合视图:

struct ProfileView: View {
    var body: some View {
        ZStack(alignment: .bottom) {
            Image("ProfilePicture")
                .resizable()
                .aspectRatio(contentMode: .fit)
            HStack {
                VStack(alignment: .leading) {
                    Text("hzy1721")
                        .font(.headline)
                    Text("An ordinary person")
                        .font(.subheadline)
                }
                Spacer()
            }
            .padding()
            .foregroundColor(.primary)
            .background(Color.primary
                            .colorInvert()
                            .opacity(0.75))
        }
    }
}

除了默认的居中对齐,还可以在三种 Stack 的 init 方法中传入 alignment 参数,指定子元素的对齐方式。

在 HStack 中 alignment 参数的类型是 VerticalAlignment,有 .top、.center、.bottom、firstTextBaseline、.lastTextBaseline。

在 VStack 中 alignment 参数的类型是 HorizontalAlignment,有 .leading、.center、.trailing。

在 HStack 中 alignment 参数的类型是 Alignment,有 9 种取值,分别是九宫格的每个位置。

Spacer 也是 Stack 中的一种对齐方式,会尽可能多地占用主方向上的空间 (HStack 的主方向是水平,VStack 是垂直),从而使主方向上的其他视图挤压到正好能包裹内容。

比如在 HStack 中有一个 Text,默认是居中对齐的,如果在右边添加一个 Spacer,Text 就会被挤到左边,成为左对齐,在左边添加 Spacer 就是右对齐。

Divider 是一条分隔线,不会影响布局,但经常在 Stack 中使用,所以也在这里说一下。Divider 只会占用一条线的空间,不会像 Spacer 一样尽可能多地占用空间。

在前端领域中对不同屏幕尺寸的适配是一个核心的问题,要求开发者尽量使用响应式布局而不是固定布局。Stack 就是响应式布局中的一种,更容易在不同尺寸的屏幕上得到一致的效果。而 frame、position 等 View modifier 则属于固定布局。

在 View modifier 中有两个方法 background 和 overlay,可以达到与 ZStack 类似的效果,具体使用哪种取决于对最终布局的尺寸的要求。如果最终布局的尺寸应该和其中某一个视图的尺寸一致,也就是该视图的大小起决定作用,就应该使用该视图的 background 或 overlay 方法。如果最终视图的尺寸应该考虑到所有视图的大小,就可以使用 ZStack。

下面是使用 overlay 实现 ProfileView 的例子:

struct ProfileViewWithOverlay: View {
    var body: some View {
        VStack {
            Image("ProfilePicture")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .overlay(ProfileDetail(), alignment: .bottom)
        }
    }
}

struct ProfileDetail: View {
    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text("Rachael Chiseck")
                    .font(.headline)
                Text("Chief Executive Officer")
                    .font(.subheadline)
            }
            Spacer()
        }
        .padding()
        .foregroundColor(.primary)
        .background(Color.primary
                        .colorInvert()
                        .opacity(0.75))
    }
}

这里的效果与 ZStack 一致。

三种 Stack 都遵循 View 协议,可以使用各种 View modifier,下面介绍一下每个 Stack 的 init 方法。

HStack

init(alignment: VerticalAlignment = .center, spacing: CGFloat? = nil, content: () -> Content)
  • VerticalAlignment 有 .top、.center、.bottom、firstTextBaseline、.lastTextBaseline。

  • spacing 是子视图之间的间隔,设为 nil 使用默认大小的间隔。

  • content 就是子视图,Content 是一个泛型类型,可以根据实际的子视图内容推断出来。这个参数实际上使用了 @ViewBuilder 注解,可以使用闭包构造视图。

VStack

init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, content: () -> Content)
  • HorizontalAlignment 有 .leading、.center、.trailing。

ZStack

init(alignment: Alignment = .center, content: () -> Content)
  • Alignment 有 9 种取值,上面讲过。

以上是关于iOSSwiftUI Stack的主要内容,如果未能解决你的问题,请参考以下文章

运行时错误:“stack around the variable…was corrupted”

Android - 在单个活动应用程序中使用工具栏按钮弹出 Back Stack

iOS SwiftUI:使用 ScrollView 和 ZStack 正确堆叠 NavigationView?

iOS SwiftUI 中 ForEach 内的 if 语句

iOS SwiftUI:ScrollView 忽略顶部安全区域

iOS SwiftUI 在与代码交互时如何调出“嵌入 VStack”之类的额外操作?