如何使 SwiftUI 按钮固定大小?

问题描述 投票:0回答:4

我正在尝试创建 2 个大小相同的按钮,但大小由按钮内的文本决定。这两个按钮是“登录”和“创建帐户”,因此“创建帐户”按钮更大。我尝试使用 .frame() 来调整大小,但这只是让它周围有额外的填充。

这是我的代码:

 HStack {
                    Button(action: {
                        print("Login button pressed")
                    }) {
                    Text("Login")
                        .padding()
                        .foregroundColor(Color.white)
                        .background(Color(UIColor.buttonColor))
                        .cornerRadius(15)
                    
                        
                    }
                    
                    Button(action: {
                        print("Create Account button pressed")
                    }) {
                    Text("Create Account")
                        .padding()
                        .foregroundColor(Color.white)
                        .background(Color(UIColor.buttonColor))
                        .cornerRadius(15)
                    }
                }

这是显示的内容

swift button swiftui
4个回答
2
投票

最好制作一个按钮样式,你可以在你的应用程序中使用它,这也将确保任何未来的堆栈按比例填充。否则你会发现你的 UI 会变得混乱,用这样的 Text()s 制作按钮。

在 HStack 中使用自定义样式布置按钮:

 HStack(spacing: 20) {
     Button("Login", action: { print("login")})
            .buttonStyle(PrimaryButtonStyle())
     Button("Create Account", action: { print("create account")})
            .buttonStyle(PrimaryButtonStyle())
    }.padding([.leading, .trailing], 10)

PrimaryButtonStyle:

struct PrimaryButtonStyle: ButtonStyle {

var backgroundColor: Color = .black
var textColor: Color = Color.white
var height: CGFloat = 46
var cornerRadius: CGFloat = 15
var fontSize: CGFloat = 15
var disabled: Bool = false
var textSidePadding: CGFloat = 30
var weight: Font.Weight = .semibold

func makeBody(configuration: Configuration) -> some View {
    configuration.label
        .padding([.leading, .trailing], textSidePadding)
        .frame(maxWidth: .infinity, maxHeight: height)
        .background(disabled ? .gray : backgroundColor)
        .foregroundColor(textColor)
        .cornerRadius(cornerRadius)
        .font(.system(size: fontSize, weight: weight, design: .default))
        .scaleEffect(configuration.isPressed ? 1.2 : 1)
        .animation(.easeOut(duration: 0.2), value: configuration.isPressed)
    }
}

结果:


0
投票

在iOS 16、macOS 13苹果引入了

Layout
协议。

此代码来自 WWDC 2022 视频Compose custom layouts with SwiftUI,它将多个按钮水平调整为等宽。

struct ButtonEqualWidth: Layout {
    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
        let maxSize = maxSize(subviews: subviews)
        let spacing = spacing(subviews: subviews)
        let totalSpacing = spacing.reduce(0, +)
        return CGSize(width: maxSize.width * CGFloat(subviews.count) + totalSpacing,
                      height: maxSize.height)
    }
    
    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
        let maxSize = maxSize(subviews: subviews)
        let spacing = spacing(subviews: subviews)
        let sizeProposal = ProposedViewSize(width: maxSize.width, height: maxSize.height)
        var x = bounds.minX + maxSize.width / 2
        for index in subviews.indices {
            subviews[index].place(
                at: CGPoint(x: x, y: bounds.midY),
                anchor: .center,
                proposal: sizeProposal)
            x += maxSize.width + spacing[index]
        }
    }
    
    func maxSize(subviews: Subviews) -> CGSize {
        let subviewSizes = subviews.map{ $0.sizeThatFits(.unspecified) }
        return subviewSizes.reduce(.zero) { currentMax, subviewSize in
            CGSize(
                width: max(currentMax.width, subviewSize.width),
                height: max(currentMax.height, subviewSize.height)
            )
        }
    }
    
    func spacing(subviews: Subviews) -> [Double] {
        return subviews.indices.map { index in
            guard index < subviews.count - 1 else { return 0.0 }
            return subviews[index].spacing.distance(
                to: subviews[index + 1].spacing,
                along: .horizontal)
        }
    }
}

在您的示例中,将此修饰符添加到两个

Text
视图

.frame(maxWidth: .infinity) 

并将

HStack
替换为
ButtonEqualWidth


0
投票

如何让两个视图的宽度或高度相同

当你想让两个视图具有相同的宽度时,这种方法同样有效:

VStack {
    Button("Log in") { }
        .foregroundColor(.white)
        .padding()
        .frame(maxWidth: .infinity)
        .background(.red)
        .clipShape(Capsule())

    Button("Reset Password") { }
        .foregroundColor(.white)
        .padding()
        .frame(maxWidth: .infinity)
        .background(.red)
       .clipShape(Capsule())
}
.fixedSize(horizontal: true, vertical: false)

有 ↑ .fixedSize(horizontal: true, vertical: false) & 没有它

重要的是要了解

.frame(maxWidth: .infinity)
也很重要


-1
投票

.frame 并将宽度设置为 UI 屏幕 - 空白应该可以工作

© www.soinside.com 2019 - 2024. All rights reserved.