Swiftui Vstack和间隔者不根据文档行为

发布于 2025-01-17 22:01:46 字数 2051 浏览 1 评论 0原文

在 SwiftUI Apple Watch 应用程序中,我们需要一些在垂直滚动视图中对齐的文本,以便:

  • 如果内容很小,则应将其放置在屏幕底部。
  • 如果内容不适合屏幕的下半部分,它应该在底部延伸到屏幕之外,这样用户就必须向下滚动才能查看其余的内容。

到目前为止,我的看法是:

import SwiftUI

struct ContentView: View {

  var body: some View {
    GeometryReader { geometry in
      ZStack {
        ScrollView(.vertical) {
          VStack(alignment: .leading, spacing: 0) {
            Spacer()
              .frame(minHeight: geometry.size.height / 2)
            Text("Title")
              .bold()
              .background(.red.opacity(0.2))
            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
              .background(.red.opacity(0.2))
          }
            .frame(minHeight: geometry.size.height - 20)
            .background(.blue.opacity(0.4))
        }
      }
        .padding(10)
        .frame(width: geometry.size.width, height: geometry.size.height)
    }
      .ignoresSafeArea()
  }
}

如您所见,Spacerframe(minHeight: ...) 部分用于将内容放置在底部。 ScrollView 的大小固定为整个屏幕。

但是,文本并未完整显示。它的外观如下:

在此处输入图像描述

如您所见,内容并非从屏幕中间开始。显然,Spacer 变得大于其 minHeight。但是,Spacer 据记录仅占用 VStack 中的多余空间。该 VStack 中没有任何多余空间,因此 Spacer 的高度应仅与其 minHeight 一样高。

我缺少什么?

这是滚动到底部时的样子:

在此处输入图像描述

为什么此文本被剪裁?

In a SwiftUI Apple Watch app, we need some text aligned in a vertical scroll view such that:

  • if the content is small, it should be placed at the bottom of the screen.
  • if the content does not fit into the lower half of the screen, it should extend off-screen at the bottom, such that the user has to scroll down to view the rest of the content.

Here's my take so far:

import SwiftUI

struct ContentView: View {

  var body: some View {
    GeometryReader { geometry in
      ZStack {
        ScrollView(.vertical) {
          VStack(alignment: .leading, spacing: 0) {
            Spacer()
              .frame(minHeight: geometry.size.height / 2)
            Text("Title")
              .bold()
              .background(.red.opacity(0.2))
            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
              .background(.red.opacity(0.2))
          }
            .frame(minHeight: geometry.size.height - 20)
            .background(.blue.opacity(0.4))
        }
      }
        .padding(10)
        .frame(width: geometry.size.width, height: geometry.size.height)
    }
      .ignoresSafeArea()
  }
}

As you can see, the Spacer and the frame(minHeight: ...) part serve to place the content on the bottom. The ScrollView's size is fixed to the whole screen.

However, the text is not displayed in full. Here's how it looks:

enter image description here

As you can see, the content does not start in the middle of the screen. Apparently the Spacer gets larger than its minHeight. However, the Spacer is documented to only take excess space in a VStack. There is not any excess space in that VStack, so the Spacer should only be as tall as its minHeight.

What am I missing?

And here's how it looks when scrolled to the bottom:

enter image description here

Why is this text clipped?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯 2025-01-24 22:01:46

解决此问题的最重要部分是布局优先级。为了防止spacer无限扩展(因为scrollview将为其内容提供多大空间),我们需要定义优先级。在不定义优先级的情况下,默认情况下,SwiftUi似乎只是在spacer和所有文本 s 50/50之间均匀地分布了布局。

我们可以降低 spacer使用 layoutpriority(_:) 修饰符。进行了一些其他次要调整,例如为vstack设置最小高度,因此短期时,文本会对准底部。

完整代码:

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            ScrollView {
                VStack(alignment: .leading, spacing: 0) {
                    Spacer()
                        .frame(maxWidth: .infinity, minHeight: geo.size.height / 2)
                        .layoutPriority(-1)

                    Text("Title")
                        .bold()
                        .background(.red.opacity(0.2))

                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
//                    Text("Much shorter text.")
                        .background(.red.opacity(0.2))
                }
                .frame(minHeight: geo.size.height)
                .background(.blue.opacity(0.4))
            }
        }
        .padding(10)
        .navigationBarHidden(true)
        .ignoresSafeArea()
    }
}

结果:

长文本短文
​sstatic.net/xpcza.gif“ alt =“短文本”>

The most important part to fix this is the layout priority. To prevent the Spacer from infinitely expanding (because ScrollView will give however much space its contents want) we need to define which takes priority. Without defining priority, by default SwiftUI appears to just evenly distribute the layout between the Spacer and all the Texts 50/50.

We can reduce the priority of the Spacer expanding with the layoutPriority(_:) modifier. A few other minor adjustments were made, such as setting a minimum height for the VStack so the text aligns to the bottom when it is short.

Full code:

struct ContentView: View {
    var body: some View {
        GeometryReader { geo in
            ScrollView {
                VStack(alignment: .leading, spacing: 0) {
                    Spacer()
                        .frame(maxWidth: .infinity, minHeight: geo.size.height / 2)
                        .layoutPriority(-1)

                    Text("Title")
                        .bold()
                        .background(.red.opacity(0.2))

                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
//                    Text("Much shorter text.")
                        .background(.red.opacity(0.2))
                }
                .frame(minHeight: geo.size.height)
                .background(.blue.opacity(0.4))
            }
        }
        .padding(10)
        .navigationBarHidden(true)
        .ignoresSafeArea()
    }
}

Result:

Long textShort text
long textshort text
飘落散花 2025-01-24 22:01:46

您根本不需要垫片,而是可以通过框架对齐来进行对齐,这在

var body: some View {
    GeometryReader { geometry in
        ZStack {
            ScrollView(.vertical) {
                VStack(alignment: .leading, spacing: 0) {
                    Spacer()
                        .frame(height: geometry.size.height / 2) // << fixed !!
                    Text("Title")
                        .bold()
                        .background(.red.opacity(0.2))
                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
                        .background(.red.opacity(0.2))
                }
                .frame(minHeight: geometry.size.height - 20, alignment: .bottom) // << !!
                .background(.blue.opacity(0.4))
            }
        }
        .padding(10)
    }
    .ignoresSafeArea()
}

用Xcode 13.2测试的情况下更合适。

You don't need spacer at all, instead alignment can be done by frame alignment, which is more appropriate in considered scenario

var body: some View {
    GeometryReader { geometry in
        ZStack {
            ScrollView(.vertical) {
                VStack(alignment: .leading, spacing: 0) {
                    Spacer()
                        .frame(height: geometry.size.height / 2) // << fixed !!
                    Text("Title")
                        .bold()
                        .background(.red.opacity(0.2))
                    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
                        .background(.red.opacity(0.2))
                }
                .frame(minHeight: geometry.size.height - 20, alignment: .bottom) // << !!
                .background(.blue.opacity(0.4))
            }
        }
        .padding(10)
    }
    .ignoresSafeArea()
}

Tested with Xcode 13.2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文