Home > Enterprise >  SwiftUI - Rounding specific corners in a button
SwiftUI - Rounding specific corners in a button

Time:07-12

I have 2 buttons side by side in a horizontal stack. I want the button to have rounded corner only on one side i.e. for the button on the left, rounded corner should be on the left and for the button on the right, rounded corner should only be on the right. Other corners should be rectangular.

I am pretty close to achieving what I want, but I do see some rounding on other corners too which I wish to be rectangular. Also even though I have set the background color, I see gray color of the button behind rounded corners.

My code:

import SwiftUI

struct CustomButtons: View {
    // Action button properties
    var rightButtonText: String? = nil
    var leftButtonText: String? = nil
    var rightButtonAction: () -> Void = {}
    var leftButtonAction: () -> Void = {}
    
    var body: some View {
        HStack {
            Button(action: { leftButtonAction() }) {
                Text("No").padding()
            }.background (
                RoundSpecificCorners(corners: [.topLeft, .bottomLeft], radius: 15).fill(Color.actionButtonsBackground)
            )
                    
            Button(action: { rightButtonAction() }) {
                Text("Yes").padding()
            }.background (
                RoundSpecificCorners(corners: [.topRight, .bottomRight], radius: 15).fill(Color.actionButtonsBackground)
            )
        }
    }
}

struct RoundSpecificCorners: Shape {
    let corners: UIRectCorner
    let radius: CGFloat
    
    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

Output:

enter image description here

What I want:

  • I am trying to get rid of small rounding on top right and bottom right of "No" button and top left and bottom left of "Yes" button. I want to have it rectangular.
  • Also trying to get rid of the default gray button background which is visible after I made the corners rounded i.e. gray background on left side of "No" button and on right side of "Yes" button.

Any idea how can I fix it?

Thanks!

Edit:

This is how it looks with the @jnpdx solution.

enter image description here

Code:

struct CustomButtons: View {
    var rightButtonText: String? = nil
    var leftButtonText: String? = nil
    var rightButtonAction: () -> Void = {}
    var leftButtonAction: () -> Void = {}
    
    var body: some View {
        HStack {
            Button(action: { leftButtonAction() }) {
                Text("No").padding().frame(minWidth: 0, maxWidth: .infinity).background( Color.blue )
                    
            }
            
            Button(action: { rightButtonAction() }) {
                Text("Yes").padding().frame(minWidth: 0, maxWidth: .infinity).background( Color.blue )
                    
            }
        }.mask(RoundedRectangle(cornerRadius: 25)).frame(maxWidth: .infinity)
    }
}

Solution that worked for me after modifying what @jnpdx had posted earlier:

var body: some View {
    HStack {
        Button(action: { leftButtonAction() }) {
            Text("No").padding().frame(minWidth: 0, maxWidth: .infinity)
        }.background( Color.blue )
        
        Button(action: { rightButtonAction() }) {
            Text("Yes").padding()
                
        }.background( Color.blue )
    }.mask(RoundedRectangle(cornerRadius: 25)).padding(.leading, 1).padding(.trailing, 1)
}

enter image description here

Thanks @jnpdx! You shouldn't have deleted your post! It was right, I just had to make slight modification probably due to watchOS version. :)

CodePudding user response:

enter image description hereInstead of using the RoundSpecificCorners, it seems like it'd be easier to just create a mask:

struct CustomButtons: View {
    // Action button properties
    var rightButtonText: String? = nil
    var leftButtonText: String? = nil
    var rightButtonAction: () -> Void = {}
    var leftButtonAction: () -> Void = {}
    
    var body: some View {
        HStack {
            Button(action: { leftButtonAction() }) {
                Text("No").padding()
                    .frame(minWidth: 0, maxWidth: .infinity) // trick to make them equally-sized
                    .background (
                        Color.yellow
                    )
            }
            
            Button(action: { rightButtonAction() }) {
                Text("Yes").padding()
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .background (
                        Color.yellow
                    )
            }
        }
        .mask {
            RoundedRectangle(cornerRadius: 25)
            // or Capsule()
        }
        .frame(width: 300)
    }
}
  • Related