我在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预览显示了问题:
对于新手的解释,我会很感激
答案 0 :(得分:3)
这里是基于运行时的方法,没有硬编码。这个想法是在绘制过程中检测可用按钮的最大宽度,并在下一个更新周期将其应用于其他按钮(无论如何,它对用户来说都是流畅的和不可见的)。
使用Xcode 11.4 / tvOS 13.4进行了测试
必填:由于使用了运行时调度的更新,因此用于测试的模拟器或设备
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”)之后。