I'm trying to create a custom toggle button control in SwiftUI where the user can see two textual values in a rounded capsule with the selected value showing in one color and the unselected value showing in a different color. The example code I am doing this for would be on a login/join screen where the user can toggle between seeing a login screen or a join screen. My issue is I can't figure out to get my background colors to work as shown below. In my example below the green color around login is showing the selected value and the gray value for join is showing the unselected option. My issue is I want the space in between the two values that looks like a white hourglass to be filled in with the same unselected color (gray).
My code is as follows:
struct LoginJoinToggle : View {
@State var showLogin: Bool = true
var body: some View {
var leftColor: Color = Color.green
var rightColor: Color = Color.gray
var leftForegroundColor: Color = Color.white
var rightForegroundColor: Color = Color.black
if (showLogin == false){
leftColor = Color.gray
rightColor = Color.green
leftForegroundColor = Color.black
rightForegroundColor = Color.white
}
return HStack{
Text("Login")
.font(.headline)
.foregroundColor(leftForegroundColor)
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(leftColor)
.cornerRadius(40.0)
.onTapGesture {self.showLogin = true}
Text("Join")
.font(.headline)
.foregroundColor(rightForegroundColor)
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(rightColor)
.cornerRadius(40.0)
.onTapGesture {self.showLogin = false}
}.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.green, lineWidth: 1)
)
}
I can get the hourglass area to fill in correctly by adding a background color of gray to the HStack as shown below but then it also shows the grey color for the entire hstack area, bleeding outside the rounded corners.
}.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.green, lineWidth: 1)
).background(Color.gray)
I've also tried setting the background to gray for the RoundedRectangle object but then it overlays that color over everything as shown below:
I'm assuming/hoping there is a way for to influence that middle area (hourglass) background color with the overlay but I can't seem to figure out how to make it work. Any suggestions would be greatly appreciated.
You can use shapes as well with your background modifier instead using a Color.
Change
}.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.green, lineWidth: 1)
).background(Color.gray)
to
}.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.green, lineWidth: 1)
).background(RoundedRectangle(cornerRadius: 40).fill(Color.pink))
and it will work.
Of course the pink color is only to make the area more visible.
What you need is one more modifier to cut off anything outside the thin green outline, add this after .background
:
.clipShape(RoundedRectangle(cornerRadius: 40))
EDIT
Capsule is a better shape to use in place of RoundedRectangle to achieve matching curves:
var body: some View {
HStack {
Text("Login")
.font(.headline)
.foregroundColor(showLogin ? Color.white : .black)
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Capsule().fill(showLogin ? Color.green : .gray))
.onTapGesture { self.showLogin = true }
Text("Join")
.font(.headline)
.foregroundColor(!showLogin ? Color.white : .black)
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Capsule().fill(!showLogin ? Color.green : .gray))
.onTapGesture { self.showLogin = false }
} .background(Capsule().fill(Color.gray))
.overlay(Capsule().stroke(Color.green, lineWidth: 1))
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With