SwiftUI如何停止Divider在HStack中垂直扩展

25

我正在使用SwiftUI创建类似于警报弹出窗口的东西,我使用UIHostingController从UIKit代码中呈现。视图如下:

VStack(spacing: 0) {
    // Some text ...   

    HStack(spacing:0) {
        Button(action: self.onCancel) { Text("Cancel") }
           .padding().inExpandingRectangle().fixedSize(horizontal: false, vertical: true)

        // This divider is the problem
        Divider() // .fixedSize()

        Button(action: self.onDelete) {  Text("Delete") }
           .padding().inExpandingRectangle().fixedSize(horizontal: false, vertical: true)
    }
}.frame(minHeight: 0)
< p > inExpandingRectangle 是我在另一个stackoverflow问题中发现的。它可以将文本居中于HStack的每个侧面。

extension View {
    func inExpandingRectangle() -> some View {
        ZStack {
            Rectangle().fill(Color.clear)
            self
        }
    }
}

看起来是这样的。{{垃圾}}。

enter image description here

如果我在分隔符上使用.fixedSize(),它会这样做。不是很糟糕,但分隔符看起来很愚蠢,而且不会扩展到按钮的大小。

enter image description here

3个回答

27

这是一个可能的简化替代方案的演示,没有那个“人为”的扩展。已在Xcode 11.4 / iOS 13.4上测试。

演示

Divider() // or Rectangle().fill(Color.gray).frame(height: 1)
HStack {
    Button(action: {}) { Text("Cancel").fixedSize() }
        .padding().frame(maxWidth: .infinity)

    Divider() // or Rectangle().fill(Color.gray).frame(width: 1)

    Button(action: {}) {  Text("Delete").fixedSize() }
        .padding().frame(maxWidth: .infinity)

}.fixedSize(horizontal: false, vertical: true)

注意:值得考虑的是使用自定义分隔符,例如:

Rectangle().fill(Color.gray).frame(width: 1) // or any other color

可能会提供更合适的视觉反馈,例如:

demo2


5
可以了,谢谢。我希望有一天我们能够得到一个详细的解释,关于SwiftUI布局是如何真正工作的。现在,我只是随意尝试并希望它能够正常工作,这不是编写代码的好方法。 - Rob N
@RobN 一遍又一遍地观看这个视频:斯坦福大学的iOS课程,第5讲。https://www.youtube.com/watch?v=ayQl_F_uMS4 - Shawn
@Shawn 谢谢,我看了那个视频。非常有用,但是对我来说还有一个很大的问题:他们所说的“灵活”到底是什么意思?他们说容器为子视图提供空间,按最不灵活到最灵活的顺序排列。但是这种灵活性是如何定义的呢?视图协议没有 var flexibility: Double 属性。 - Rob N
@RobN 布局行为
  1. 一些视图会尽可能小以适应它们的内容。(我将称之为“拉入”视图。)例如:Button Z/H/VStack、Text等。
  2. 一些视图会推出以填充所有可用空间。(我将称之为“推出”视图。)了解这两种行为可以帮助您在使用不同视图时预测会发生什么。例如-颜色
- Darshan Mothreja

10
fixedSize() 修改器放在 HStack 上而不是 Divider 上可以解决问题。
    var body : some View {
        VStack(spacing: 0) {
            // Some text ...
            Text("gsfdsfkajflkasdjflkas,jdflaskjf")
            HStack(spacing:0) {
                Button(action: {print("hi")}) { Text("Cancel") }
                    .padding().inExpandingRectangle().fixedSize(horizontal: true, vertical: true)

                // This divider is the problem
                Divider()


                Button(action: {print("hello")}) {  Text("Delete") }
                    .padding().inExpandingRectangle().fixedSize(horizontal: true, vertical: true)
            }.fixedSize()        <------- Insert this
        }.frame(minHeight: 0)
    }

结果:

在这里输入图片描述


1
谢谢。我需要稍微变化一下:在HStack上使用.fixedWidth(horizontal: false, vertical: true),以保持按钮文本居中,但这个答案还是有帮助的。 - Rob N
我使用了.fixedSize(horizontal: false, vertical: true) - Daniel Elkington

0
你可以尝试下面的代码,希望能对你有所帮助(Xcode 11.2.1)。 注意:根据你的需求更改字体框架颜色
var body: some View {

    VStack(spacing: 0) {

        Text("Delete")
            .font(Font.system(size: 20, weight: .bold))

        Text("Are you sure you want to delete ?")
            .font(Font.system(size: 18, weight: .regular))
            .padding([.top,.bottom], 15)

        Rectangle().fill(Color.gray.opacity(0.5)).frame(height:0.5)

        HStack(spacing:0) {

            Button(action: {
                //Your action
            }) {
                Text("Cancel")
                    .foregroundColor(Color.black)
                    .font(Font.system(size: 18, weight: .medium))
            }
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)

            Rectangle().fill(Color.gray.opacity(0.5)).frame(width:0.5,height:20)

            Button(action: {
                //Your action
            }) {
                Text("Delete")
                    .font(Font.system(size: 18, weight: .medium))
                    .foregroundColor(Color.red)
            }
            .frame(minWidth: 150, maxWidth: .infinity, minHeight: 40, maxHeight: 40, alignment: .center)
        }
    }
}

输出:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接