SwiftUI:两个具有相同宽度/高度的按钮

时间:2020-05-16 17:47:44

标签: swift user-interface swiftui

我在H / VStack中有2个按钮。它们都包含一些文本,在我的示例中为“播放”和“暂停”。我希望两个按钮都具有由最大按钮确定的相同宽度(和高度)。我在SO上找到了一些答案,但不幸的是我无法使此代码正常工作。

以下代码说明了这个问题:

import SwiftUI

struct ButtonsView: View {
    var body: some View {
        VStack {
            Button(action: { print("PLAY tapped") }){
                Text("Play")
            }

            Button(action: { print("PAUSE tapped") }) {
                Text("Pause")
            }
        }
    }
}

struct ButtonsView_Previews: PreviewProvider {
    static var previews: some View {
        ButtonsView()
    }
}

Xcode的tvOS预览显示了问题:

enter image description here

对于新手的解释,我会很感激

3 个答案:

答案 0 :(得分:3)

这里是基于运行时的方法,没有硬编码。这个想法是在绘制过程中检测可用按钮的最大宽度,并在下一个更新周期将其应用于其他按钮(无论如何,它对用户来说都是流畅的和不可见的)。

使用Xcode 11.4 / tvOS 13.4进行了测试

必填:由于使用了运行时调度的更新,因此用于测试的模拟器或设备

demo

struct ButtonsView: View {
    @State private var maxWidth: CGFloat = .zero
    var body: some View {
        VStack {
            Button(action: { print("PLAY tapped") }){
                Text("Play")
                    .background(rectReader($maxWidth))
                    .frame(minWidth: maxWidth)
            }.id(maxWidth) // !! to rebuild button (tvOS specific)

            Button(action: { print("PAUSE tapped") }) {
                Text("Pause Long Demo")
                    .background(rectReader($maxWidth))
                    .frame(minWidth: maxWidth)
            }.id(maxWidth) // !! to rebuild button (tvOS specific)
        }
    }

    // helper reader of view intrinsic width
    private func rectReader(_ binding: Binding<CGFloat>) -> some View {
        return GeometryReader { gp -> Color in
            DispatchQueue.main.async {
                binding.wrappedValue = max(binding.wrappedValue, gp.frame(in: .local).width)
            }
            return Color.clear
        }
    }

}

答案 1 :(得分:-1)

我认为最好的解决方案是使用GeometryReader,它可以调整width内容中Button的大小。但是,您需要检查是否在GeometryReader周围设置了width包装器,因为否则它将尝试使用整个屏幕宽度。 (取决于您在哪里使用该视图,或者它是您的主视图)

VStack
{
    GeometryReader { geo in

        VStack
        {
            Button(action: { print("PLAY tapped") }){
                Text("Play")
                .frame(width: geo.size.width)
            }
            .border(Color.blue)

            Button(action: { print("Pause tapped") }){
                Text("PAUSE")
                .frame(width: geo.size.width)
            }
            .border(Color.blue)
        }

    }
}
.frame(width: 100)
.border(Color.yellow)

...看起来像那样。

答案 2 :(得分:-2)

如果在Spacer()后面紧跟Text("Play"),会发生什么?我认为这可能会延长“播放”按钮。

或者在之前,在Text(“ Play”)之后