如何在按钮边缘上制作cornerRadius,以便在swiftUI中不剪裁边缘

Posted

技术标签:

【中文标题】如何在按钮边缘上制作cornerRadius,以便在swiftUI中不剪裁边缘【英文标题】:How to make cornerRadius on Button edges so that edges are not clipped in swiftUI 【发布时间】:2019-06-10 00:06:24 【问题描述】:

我正在尝试使用 SwiftUI。我不知道如何获得一个带有边框宽度的圆形按钮。以下是我尝试过的代码。

这是我的代码

struct ArrowButton : View 
    var body: some View 
        return Button(action: ) 
            HStack 
                Text("SEE ALL")
                    .font(.headline)
                    .color(Color.init(red: 0.627, green: 0.776, blue: 0.965))
                Image(systemName: "arrow.right")
                    .font(Font.title.weight(.bold))
            
        
            .padding(.all, 9.0)
            .border(Color.init(red: 0.627, green: 0.776, blue: 0.965))
            .cornerRadius(5.0)
    

这是我的看法

我应该使用什么修饰符

    增加边框宽度? 去除下图所示的剪裁效果?

【问题讨论】:

【参考方案1】:

View.border(:width:cornerRadius) 方法在最终的 Xcode 11 版本中不可用,但您可以通过同时应用 cornerRadiusoverlay 修饰符来获得相同的结果:

Button(action: ) 
    VStack 
        Image(systemName: "star.fill")
        Text("Hello world!")
    
    .padding()
    .accentColor(Color(.systemRed))
    .background(Color(UIColor.systemRed.withAlphaComponent(0.4)))
    .cornerRadius(4.0)
    .overlay(
        RoundedRectangle(cornerRadius: 4).stroke(Color(.systemRed), lineWidth: 2)
    )

结果:

【讨论】:

【参考方案2】:

为 Swift 5 和 ios 13.4+ 更新了 Press States!

没有一个示例适用于同时具有深色和白色背景颜色的按钮,而且它们都没有按下状态更新,所以我构建了这个 LargeButton 视图,您可以在下面看到。

示例照片

使用示例

// White button with green border.
LargeButton(title: "Invite a Friend", 
            backgroundColor: Color.white, 
            foregroundColor: Color.green) 
                        print("Hello World")
                    

// Yellow button without a border
LargeButton(title: "Invite a Friend", 
            backgroundColor: Color.yellow) 
                        print("Hello World")
                    

代码

struct LargeButtonStyle: ButtonStyle 
    
    let backgroundColor: Color
    let foregroundColor: Color
    let isDisabled: Bool
    
    func makeBody(configuration: Self.Configuration) -> some View 
        let currentForegroundColor = isDisabled || configuration.isPressed ? foregroundColor.opacity(0.3) : foregroundColor
        return configuration.label
            .padding()
            .foregroundColor(currentForegroundColor)
            .background(isDisabled || configuration.isPressed ? backgroundColor.opacity(0.3) : backgroundColor)
            // This is the key part, we are using both an overlay as well as cornerRadius
            .cornerRadius(6)
            .overlay(
                RoundedRectangle(cornerRadius: 6)
                    .stroke(currentForegroundColor, lineWidth: 1)
        )
            .padding([.top, .bottom], 10)
            .font(Font.system(size: 19, weight: .semibold))
    


struct LargeButton: View 
    
    private static let buttonHorizontalMargins: CGFloat = 20
    
    var backgroundColor: Color
    var foregroundColor: Color
    
    private let title: String
    private let action: () -> Void
    
    // It would be nice to make this into a binding.
    private let disabled: Bool
    
    init(title: String,
         disabled: Bool = false,
         backgroundColor: Color = Color.green,
         foregroundColor: Color = Color.white,
         action: @escaping () -> Void) 
        self.backgroundColor = backgroundColor
        self.foregroundColor = foregroundColor
        self.title = title
        self.action = action
        self.disabled = disabled
    
    
    var body: some View 
        HStack 
            Spacer(minLength: LargeButton.buttonHorizontalMargins)
            Button(action:self.action) 
                Text(self.title)
                    .frame(maxWidth:.infinity)
            
            .buttonStyle(LargeButtonStyle(backgroundColor: backgroundColor,
                                          foregroundColor: foregroundColor,
                                          isDisabled: disabled))
                .disabled(self.disabled)
            Spacer(minLength: LargeButton.buttonHorizontalMargins)
        
        .frame(maxWidth:.infinity)
    

【讨论】:

【参考方案3】:

指定边框的宽度和圆角半径:

.border(Color.init(red: 0.627, green: 0.776, blue: 0.965),
        width: 6.0,
        cornerRadius: 12.0))

例如这段代码:

struct ContentView : View 
    var body: some View 
        return Button(action: ) 
            HStack 
                Text("SEE ALL")
                    .font(.headline)
                    .color(Color.init(red: 0.627, green: 0.776, blue: 0.965))
                Image(systemName: "arrow.right")
                    .font(Font.title.weight(.bold))
            
            
            .padding(.all, 20.0)
            .border(Color.init(red: 0.627, green: 0.776, blue: 0.965),
                    width: 6.0,
                    cornerRadius: 40.0)
    

这个视图的结果:

                                 

【讨论】:

奇怪的是,当我在那个边界函数中添加圆角半径时它可以工作,但是当我之后有圆角半径代码时它会失败。无论如何,谢谢,它有效 @ielyamani,但是如何将cornerRadius 添加到视图而不是边框​​?这种方法不起作用...:Button(action: tap) Text(optionItem.actionText) .color(Color.white) .frame(width: bounds.width * 0.75, height: 50, alignment: .center) .cornerRadius(12) .background(optionItem.color) @AlexShvets 顺序很重要:.background(Color.red),然后是.cornerRadius(12)。即使应用圆角半径后,视图仍由矩形定义。 这个功能好像不存在了。

以上是关于如何在按钮边缘上制作cornerRadius,以便在swiftUI中不剪裁边缘的主要内容,如果未能解决你的问题,请参考以下文章

防止不均匀的Border CornerRadius

如何创建xamarin表单按钮左角半径

如何根据按钮框架正确计算cornerRadius

recharts中饼图提供cornerRadius后如何加入

如何统一使相机的边缘变灰

同时执行cornerRadius和约束动画