swift nub
swift nub

Reputation: 2937

How to make cornerRadius on Button edges so that edges are not clipped in swiftUI

I am experimenting with SwiftUI. I do not know how to get a rounded button with a borderWidth. Below is the code that I have tried.

Here is my code

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)
    }
}

And here is how my view looks enter image description here

What modifiers should i use to

  1. Increase the border width?
  2. Remove the clipping effect shown below?

Upvotes: 12

Views: 10612

Answers (3)

ricardopereira
ricardopereira

Reputation: 11683

The View.border(:width:cornerRadius) method is not available in the final Xcode 11 version but you can achieve the same result by applying both cornerRadius & overlay modifiers:

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)
    )
}

Result:

Button example using the overlay modifier

Upvotes: 14

Zorayr
Zorayr

Reputation: 24922

Updated for Swift 5 & iOS 13.4+ with Press States!

None of the examples worked for buttons with both dark and white background colors as well as none of them had press state updates, so I built this LargeButton view that you can see below.

Example Photos

enter image description here

Example Use

// 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")
                    }

Code

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)
    }
}

Upvotes: 7

ielyamani
ielyamani

Reputation: 18591

Specify the width and corner radius for the border:

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

For example this code:

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)
    }
}

results in this view:

                                  rounded button

Upvotes: 3

Related Questions