SwiftUI:无法将图像对齐到ZStack的顶部

时间:2020-01-24 20:39:58

标签: ios swift swiftui

我不知道如何在pd.concat([df1,pd.DataFrame(columns=['qx'+str(i) for i in range(11)], data=[ser1.T.loc[:,i:i+10].values.flatten().tolist() for i in df1['age']])], axis=1) prod age qx0 qx1 qx2 qx3 qx4 qx5 qx6 qx7 qx8 qx9 qx10 0 Winalto_eu 28 2.9 3.0 3.2 3.4 3.7 4.1 4.6 5.1 5.6 6.1 6.7 1 Winalto_uc 25 2.7 2.8 2.8 2.9 3.0 3.2 3.4 3.7 4.1 4.6 5.1 2 CEM_eu 30 3.2 3.4 3.7 4.1 4.6 5.1 5.6 6.1 6.7 7.5 8.2 上方对齐Image视图,默认情况下,SwiftUI中的视图位于其父级的中心,然后我们使用堆栈来对齐它们,我有以下代码:

ZStack

如何将图像放置在顶部?

enter image description here

3 个答案:

答案 0 :(得分:13)

要告诉ZStack在其中对齐特定内容,请使用alignment参数对其进行配置:

ZStack(alignment: .top) {
    Color.clear
    Image(...)
    Text("Hello, World!")
}

(Color.clear会扩展为填充所有可用空间,因此这会强制ZStack变得与封闭视图一样大,而无需添加.frame()。)

这将使所有内容排在最前面,这可能不是您想要的。您可以通过嵌套ZStack使其按照您希望的对齐方式来解决此问题:

ZStack{
    ZStack(alignment: .top) {
        Color.clear
        Image(...)        // This will be at the top
    }
    Text("Hello, World!") // This will be centered
}

也就是说,在此示例中,我可能会使用.background

ZStack {
    Color.clear
    Text("Hello, World!")
}
.background(Image(...), alignment: .top)

如果只有一个视图,则可以摆脱ZStack并改用框架:

Text("Hello, World!")
    .frame(maxHeight: .infinity)
    .background(Image(uiImage:#imageLiteral(resourceName: "image.jpg")), 
                alignment: .top)

请记住,在这种情况下,图像将绘制在其框架之外。在很多情况下都很好(这是完全合法的),但有时可能很重要(例如,如果将其放入堆栈中)。您可以在末尾添加.border(Color.green),以了解其工作原理。


这个示例确实深入到SwiftUI布局的核心,因此值得了解正在发生的事情。这不是解决方法或技巧,因此您应该到达感觉很正常的地方。

顶级内容视图(包含ZStack的视图)将整个空间提供给ZStack。 ZStack始终是包含其内容的大小,,因此,ZStack首先需要布局其子级。它根据对齐方式对它们进行布局,然后调整大小以使其完全适合它们。因此,通过顶部对齐(但没有Color.clear),图像位于ZStack的顶部。 ZStack与Image大小完全相同。

然后,顶级内容视图将ZStack置于其中心。

ZStack布置其子级的方式类似于内容视图的方式。它提供了所提供的所有空间,然后子视图确定了它们的大小。 视图始终确定自己的大小。“图像”和“文本”是固定大小的视图,因此它们只是其内容的大小。但是“颜色”是一个大小灵活的视图。它接受ZStack提供的全部空间(与顶级内容视图提供的空间相同),并以其大小返回。由于ZStack必须完全包含其子级,因此ZStack现在是顶级内容视图的大小,并且一切都按您期望的方式进行,并在屏幕顶​​部对齐。

与您最初使用.frame()进行比较:

ZStack {
   Image("bgImage")
   Text("Hello, World!")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red) //this is for debugging purposes, to show the area of the ZStack

首先,我想重点谈谈您的评论,因为它不正确。这不是ZStack的范围。 ZStack恰好是其内容(图像和文本)的大小。您将背景放在框架视图上,并且框架视图更大。

人们的主要困惑是他们认为.frame(...)会改变其附加的View的大小。那根本不正确。与以前一样, ZStack始终是其内容的大小。 .frame()创建一个请求大小的全新视图。然后,根据框架的对齐方式将包装后的视图放置在其内部。因此,在此示例中,它的工作方式如下:

顶级-背景-框架-ZStack-{图片文字}

顶级视图将所有空间提供给背景。背景是它们所包含内容的大小,因此它为框架提供了所有空间。框架在两个方向上都很灵活(由于max字段),因此它忽略了其子项的大小,并选择为其提供的大小。

然后,框架将所有空间提供给ZStack。 ZStack布置其子项,并返回其大小恰好包含它们的大小。

然后,框架根据框架的对齐方式放置ZStack(.center,因为这是默认设置)。如果您将框架的对齐方式设置为.top,则ZStack会被放置在框架的顶部(但文本将在在ZStack中居中,而不是在框架中)

然后它向后台报告它与顶层视图一样大(因为它具有灵活性)。

然后,背景宣称与顶级内容视图具有相同的大小。

最后,顶级内容视图将背景置于其中心。

答案 1 :(得分:-1)

因此不利于您的一件事是无限的maxHeight修饰符,假设您不希望图像和视图底部之间有一些空间。

.edgesIgnoringSafeArea(.all)

您可能只需要告诉ZStack忽略安全区域插图即可。

struct ContactsView: View {
  var body: some View {

    ZStack {
      Image("bgImage")
      Text("Hello, World!")
    }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color.red).edgesIgnoringSafeArea(.all)

  }
}

如果需要在底部和图像之间留出空间,请将ZStack包裹在VStack中,并在VStack的底部扔一个垫片。

struct ContactsView: View {
  var body: some View {
    VStack {

      ZStack {
        Image(systemName: "bgImage")
        Text("Hello, World!")
      }.frame(maxWidth: .infinity, maxHeight: 300).background(Color.red)

      Spacer()

    }.edgesIgnoringSafeArea(.all)
  }
}

答案 2 :(得分:-1)

ZStack {
    Image("background")
         .resizable()
         .scaledToFill()
         .edgesIgnoringSafeArea(.all)
}

添加 .edgesIgnoringSafeArea(.all)