【问题标题】:SwiftUI: VStack ignoring wrapping ZStack frameSwiftUI:VStack 忽略包装 ZStack 框架
【发布时间】:2021-07-31 05:53:43
【问题描述】:

我目前正在研究一个相当简单的视图:一堆H/VStacks 使用ZStack 在彼此之上。 我正在使用 .frame 修饰符限制 ZStack 的大小。出于某种原因,我的嵌套 VStack 似乎忽略了它的父框架。 我想要实现的是VStack 匹配ZStack 的框架,就像Image 一样。

struct CourseTileView: View {
    let viewModel: CourseTileViewModel
    var body: some View {
        ZStack {
            Image(uiImage: viewModel.thumbnail)
                .resizable()
                .scaledToFill()
                .clipped()
            VStack {
                HStack {
                    HStack {
                        ForEach(viewModel.mediaTypes.sorted(), id: \.self) {
                            $0.image
                                .foregroundColor(.white)
                                .frame(width: 20, height: 20)
                        }
                    }
                    Spacer()
                    RedCapsuleTextView(title: "NEW")
                        .isHidden(!viewModel.isBadgeVisible)
                }
                Spacer()
                Text(viewModel.title)
                    .foregroundColor(.white)
                    .font(.mpText.bold())
                ProgressBar(
                    tintColor: .white,
                    backgroundColor: .white.alpha(0.3),
                    progress: viewModel.progress
                )
                .frame(width: 144, height: 7)
                .isHidden(viewModel.progress == .zero)
            }
            .padding()
        }
        .frame(width: 164, height: 270)
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }
}

蓝色边框是预览中报告的VStack的大小:

VStack也需要设置框架吗?

更新

使用 GeometryReader 可以解决问题,但是……这是要走的路吗?

ZStack {
    GeometryReader { geometry in
        Image(uiImage: viewModel.thumbnail)
            .resizable()
            .scaledToFill()
            .clipped()
        VStack {
            // Content
        }
        .frame(maxWidth: geometry.size.width)
        .padding(.horizontal, Margin.small)
        .padding(.vertical, Margin.medium)
    }
    .frame(width: 164, height: 270)
    .clipShape(RoundedRectangle(cornerRadius: 10))
}

【问题讨论】:

  • 您希望您的图像和内容(即 VStack)尊重 (164X270) 的框架还是什么?这三件事中哪一件是你的基础? frame 还是 Image 还是 VStack?
  • 我希望 ZStack 成为基础,因此我将框架设置在那里。每个子视图都应该尊重 ZStack 的框架。

标签: swift swiftui


【解决方案1】:

您可能需要使用overlay 而不是ZStack。这会强制覆盖视图(您的VStack)约束到底部视图(您的Image)。这是您的代码的简化版本:

struct CourseTileViewModel {
    var title = "How to deal with stack overflow questions"
    var thumbnail = UIImage(named: "Image")!
}
struct ContentView21: View {
    let viewModel = CourseTileViewModel()
    var body: some View {
        Image(uiImage: viewModel.thumbnail)
            .resizable()
            .scaledToFill()
            .clipped()
            .frame(width: 164, height: 270)
            .clipShape(RoundedRectangle(cornerRadius: 10))
            
            /// overlay will be the exact same size as the image
            .overlay(
                VStack {
                    Spacer()
                    Text(viewModel.title)
                        .fontWeight(.bold)
                }
                .frame(maxWidth: .infinity) /// make it take up as much width as possible
                .padding()
                .border(Color.blue)
            )
            
    }
}

结果:

【讨论】:

    猜你喜欢
    • 2020-01-22
    • 2014-07-17
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多