Button("Button Title") {\n \/\/ Action to perform on tap\n}<\/code><\/pre><\/div>\n\n\n\nThis creates a button that simply consists of the text Button Title<\/code> and performs the action specified in the closure.<\/p>\n\n\n\n
The most basic SwiftUI button with only text<\/figcaption><\/figure><\/div>\n\n\nYou can create more complicated layout in the button as below:<\/p>\n\n\n\n
Button {\n \/\/ Action to perform on tap\n} label: {\n \/\/ Contents of the button\n HStack {\n Image(systemName: "command")\n Text("Button Title")\n }\n}<\/code><\/pre><\/div>\n\n\n\n
A SwiftUI button with image and text<\/figcaption><\/figure><\/div>\n\n\nThis still doesn’t look like much of a button though. We want to be able to specify more aspects of the button with things like background colour, foreground colour, border etc.<\/p>\n\n\n\n
Customising a Button<\/h2>\n\n\n\n
SwiftUI provides .buttonStyle(_ style: ButtonStyle)<\/code> method to allow us to define how the button should be styled. Lets create a custom style that we can apply to buttons for quick styling:<\/p>\n\n\n\nstruct CustomButtonStyle: ButtonStyle {\n public let enabledBackgroundColor: Color\n public let disabledBackgroundColor: Color\n public let enabledForegroundColor: Color\n public let disabledForegroundColor: Color\n public let cornerRadius: CGFloat\n public let borderColor: Color?\n\n init(\n enabledBackgroundColor: Color,\n disabledBackgroundColor: Color,\n enabledForegroundColor: Color,\n disabledForegroundColor: Color,\n cornerRadius: CGFloat = 12.0,\n borderColor: Color? = nil\n ) {\n self.enabledBackgroundColor = enabledBackgroundColor\n self.disabledBackgroundColor = disabledBackgroundColor\n self.enabledForegroundColor = enabledForegroundColor\n self.disabledForegroundColor = disabledForegroundColor\n self.cornerRadius = cornerRadius\n self.borderColor = borderColor\n }\n\n @Environment(\\.isEnabled) private var isEnabled\n\n func makeBody(configuration: Configuration) -> some View {\n configuration.label\n .font(.system(size: 18.0, weight: .semibold))\n .padding()\n .background(backgroundColor)\n .foregroundColor(foregroundColor)\n .cornerRadius(cornerRadius)\n .overlay(\n RoundedRectangle(cornerRadius: cornerRadius)\n .stroke(\n borderColor ?? .clear,\n lineWidth: 1.0\n )\n )\n .contentShape(RoundedRectangle(cornerRadius: cornerRadius))\n }\n\n var backgroundColor: Color {\n isEnabled ? enabledBackgroundColor : disabledBackgroundColor\n }\n\n var foregroundColor: Color {\n isEnabled ? enabledForegroundColor : disabledForegroundColor\n }\n}<\/code><\/pre><\/div>\n\n\n\nconfiguration.label<\/code> in the<\/code> makeBody<\/code> method above is the content that is passed as the button’s body. Most of the modifiers above are self explanatory but lets have a quick look at each of them individually:<\/p>\n\n\n\n.font(.system(size: 18.0, weight: .semibold))<\/code> applies system font with size 18.0 in semibold weight<\/li>.padding()<\/code> applies default padding to all 4 sides. This can be customised by passing explicit values for each side as needed<\/li>.background(backgroundColor)<\/code> applies background color to the button<\/li>.foregroundColor(foregroundColor)<\/code> applies foreground color to the button contents<\/li>.cornerRadius(cornerRadius)<\/code> applies the corner radius to the button<\/li>.overlay()<\/code> applies a RoundedRectangle border with border color and line width as specified<\/li>- We could also add animation on button press using
configuratioin.isPressed<\/code> value as needed<\/li><\/ul>\n\n\n\nThis style can be applied to any Button as below:<\/p>\n\n\n\n
Button {\n \/\/ Action to perform on tap\n} label: {\n \/\/ Contents of the button\n HStack {\n Image(systemName: "command")\n Text("Button Title")\n }\n}\n.buttonStyle(\n CustomButtonStyle(\n enabledBackgroundColor: .black,\n disabledBackgroundColor: .gray,\n enabledForegroundColor: .white,\n disabledForegroundColor: .white\n )\n)<\/code><\/pre><\/div>\n\n\n\n
A styled SwiftUI button<\/figcaption><\/figure><\/div>\n\n\nCode Cleanup<\/h2>\n\n\n\n
That looks much better but we can clean it up a little bit for improved reusability. Most apps have a handful of button styles that are reused through out the app so it would be great to have a way to apply the button style in a less verbose way:<\/p>\n\n\n\n
extension ButtonStyle where Self == CustomButtonStyle {\n static var primaryButtonStyle: CustomButtonStyle {\n CustomButtonStyle(\n enabledBackgroundColor: .black,\n disabledBackgroundColor: .gray,\n enabledForegroundColor: .white,\n disabledForegroundColor: .white\n )\n }\n\n static var secondaryButtonStyle: CustomButtonStyle {\n CustomButtonStyle(\n enabledBackgroundColor: .clear,\n disabledBackgroundColor: .gray,\n enabledForegroundColor: .black,\n disabledForegroundColor: .white,\n borderColor: .black\n )\n }\n\n static var destructiveButtonStyle: CustomButtonStyle {\n CustomButtonStyle(\n enabledBackgroundColor: .red,\n disabledBackgroundColor: .gray,\n enabledForegroundColor: .white,\n disabledForegroundColor: .white\n )\n }\n\n static var primaryCircularStyle: CustomButtonStyle {\n CustomButtonStyle(\n enabledBackgroundColor: .black,\n disabledBackgroundColor: .gray,\n enabledForegroundColor: .white,\n disabledForegroundColor: .white,\n cornerRadius: 999\n )\n }\n}<\/code><\/pre><\/div>\n\n\n\nNow we can quickly apply these different styles as below to get the same effect as before:<\/p>\n\n\n\n
Button {\n \/\/ Action to perform on tap\n} label: {\n \/\/ Contents of the button\n HStack {\n Image(systemName: "command")\n Text("Button Title")\n }\n}\n.buttonStyle(.primaryButtonStyle)<\/code><\/pre><\/div>\n\n\n\nThat is a much cleaner call site. Most apps use a very explicit style of buttons through out the app so we can clean this up further.<\/p>\n\n\n\n
struct CustomButton: View {\n let title: String?\n let icon: Image?\n let buttonStyle: CustomButtonStyle\n let action: () -> Void\n\n init(\n title: String? = nil,\n icon: Image? = nil,\n buttonStyle: CustomButtonStyle = .primaryButtonStyle,\n action: @escaping () -> Void\n ) {\n self.title = title\n self.icon = icon\n self.buttonStyle = buttonStyle\n self.action = action\n }\n\n var body: some View {\n Button(action: action) {\n HStack {\n icon\n\n if let title = title {\n Text(title)\n }\n }\n }\n .buttonStyle(buttonStyle)\n .frame(minWidth: 40, minHeight: 40)\n }\n}<\/code><\/pre><\/div>\n\n\n\nAnd now the usage becomes even cleaner and consistent across the app:<\/p>\n\n\n\n
VStack(spacing: 20) {\n CustomButton(\n title: "Primary Button",\n icon: Image(systemName: "command"),\n buttonStyle: .primaryButtonStyle\n ) {\n \/\/ Do something\n }\n\n CustomButton(\n title: "Secondary Button",\n buttonStyle: .secondaryButtonStyle\n ) {\n \/\/ Do something\n }\n\n CustomButton(\n title: "Destructive Button",\n icon: Image(systemName: "command"),\n buttonStyle: .destructiveButtonStyle\n ) {\n \/\/ Do something\n }\n\n CustomButton(\n icon: Image(systemName: "command"),\n buttonStyle: .primaryCircularStyle\n ) {\n \/\/ Do something\n }\n}<\/code><\/pre><\/div>\n\n\n\nThat is much cleaner to use now.<\/p>\n\n\n
\n
Multiple SwiftUI buttons with different styles applied to each<\/figcaption><\/figure><\/div>\n\n\nBonus<\/h2>\n\n\n\n
Another advantage of styling buttons using ButtonStyle<\/code> is that these button styles can be reused wiith NavigationLink<\/code> to create navigation links that look exactly like rest of the buttons in your app<\/p>\n\n\n\nNavigationLink(\n "Button Title",\n destination: DetailsView()\n)\n.buttonStyle(.primaryButtonStyle)<\/code><\/pre><\/div>\n\n\n\nHopefully this provides a good understanding of not just how Buttons work in SwiftUI and how they can be styled but also provides a nice framework for how you can create a Button as a component. These can then be used easily through out the app and that provides a much consistent look and feel in your app.<\/p>\n","protected":false},"excerpt":{"rendered":"
Tested on Xcode 13.4 with iOS 14 Button is one of the most fundamental building block for mobile apps. SwiftUI provides a very flexible way to create and customise buttons in your app. Creating a Button Button in SwiftUI can simply be created as below: This creates a button that simply consists of the text … <\/p>\n
Continue reading “SwiftUI Button\ufffc”<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,3],"tags":[5,4],"yoast_head":"\nSwiftUI Button\ufffc - techjourney.me<\/title>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\t\n\t\n