Welcome to Part 2 of our SwiftUI series! After understanding the basics in Part 1, it’s time to focus on building beautiful, dynamic, and interactive user interfaces with SwiftUI. This part is all about taking your UI skills to the next level by exploring essential components and techniques for crafting seamless app experiences.
So, let’s start your Swift journey and understand each topic in detail!
SwiftUI Views and Modifiers
The main funda of SwiftUI is Views and Modifiers, which make UI simple and reusable. Views are the building blocks of your app, and Modifiers customize these views.
Let’s understand in detail!
Creating Reusable Views
Russable views mean a single component that you can use over and over again, in different places, without duplicating code.
Example: Create a custom button that can be used everywhere.
import SwiftUI
struct CustomButton: View {
var title: String
var backgroundColor: Color
var body: some View {
Text(title)
.font(.headline)
.padding()
.foregroundColor(.white)
.background(backgroundColor)
.cornerRadius(10)
}
}
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
CustomButton(title: "Login", backgroundColor: .blue)
CustomButton(title: "Sign Up", backgroundColor: .green)
}
.padding()
}
}
custom button is a rasable view which accepts title and background color.
This view can be customized to use in different places.
Customizing Views with Modifiers
Modifiers are a core feature of Swifty that modify views. They work with a declarative syntax.
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, SwiftUI!")
.font(.largeTitle) // Increase the font size
.foregroundColor(.blue) // Change the text color
.padding() // Give spacing on 4 sides of the text
.background(Color.yellow) // Background color
.cornerRadius(15) // Round the corner
}
}
- font(.largeTitle): Makes the font size large.
- foregroundColor(.blue): Sets the text color to blue.
- padding(): Adds padding on 4 sides of the text.
- background(Color.yellow): Apply a yellow background.
- cornerRadius(15): Rounds the corners with a 15-point radius.
struct LabeledContentView: View {
var body: some View {
VStack {
Text("title")
.font(.largeTitle)
.padding(.bottom, 5)
Text("subtitle")
.font(.subheadline)
.foregroundColor(.gray)
Spacer()
}
.padding()
}
}
Practical Examples for UI Components
Example 1: Custom Card View
struct CustomCard: View {
var title: String
var subtitle: String
var icon: String
var body: some View {
HStack {
Image(systemName: icon)
.font(.largeTitle)
.foregroundColor(.blue)
VStack(alignment: .leading) {
Text(title)
.font(.headline)
Text(subtitle)
.font(.subheadline)
.foregroundColor(.gray)
}
.padding(.leading)
}
.padding()
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
}
}
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
CustomCard(title: "SwiftUI", subtitle: "Declarative UI Framework", icon: "swift")
CustomCard(title: "iOS Development", subtitle: "Build amazing apps", icon: "iphone")
}
.padding()
.background(Color(UIColor.systemGroupedBackground))
}
}
CustomCard is a reusable card view that customizes with dynamic content.
Shadows and corner radius make the card visually appealing.
Button with Multiple Modifiers
struct ContentView: View {
var body: some View {
Button(action: {
print("Button tapped!")
}) {
Text("Tap Me")
.font(.title2)
.fontWeight(.bold)
.padding()
.frame(maxWidth: .infinity)
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(12)
.shadow(color: .purple.opacity(0.5), radius: 5, x: 0, y: 5)
}
.padding()
}
}
The button performs an action when pressed.
The button is stylized by applying multiple modifiers: frame, corner radius, and shadow.
Working with Stacks
Stacks are the simplest and most powerful tool for creating layouts in Swifty. There are three types of them:
- VStack – Vertically aligned views.
- HStack – Horizontally aligned views.
- ZStack – Overlapping views on top of each other.
Aap stacks ko combine karke complex UI designs easily create kar sakte ho. Let’s understand them step by step!
Using VStack
VStack stacks views vertically. The default alignment is center, but you can customize.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
Text("Welcome to SwiftUI")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.blue)
Text("Create amazing UIs easily!")
.font(.subheadline)
.foregroundColor(.gray)
}
.padding()
}
}
Spacing: Defines the gap between views.
Text is customized with the font and foreground color modifiers.
Using HStack
Aligns manual views horizontally. The default alignment is center.
struct ContentView: View {
var body: some View {
HStack(spacing: 15) {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("Favorite")
.font(.headline)
}
.padding()
}
}
When the app is sent to the background (such as pressing the Home button), the app becomes temporarily inactive.An image and text are placed horizontally in the manual.
Spacing: Sets the distance between the image and text.
Using ZStack
ZStacks views on top of each other, like layers.
struct ContentView: View {
var body: some View {
ZStack {
Color.blue // Background color
.ignoresSafeArea()
Text("SwiftUI")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white)
}
}
}
Color.blue is the background of the ZStack.
Text is displayed as a layer on top of it.
ignoresSafeArea(): extends the background to the entire area of the screen.
Combining Stacks for Complex Layouts
Combine stacks to create hierarchical layouts.
struct ContentView: View {
var body: some View {
VStack(spacing: 30) {
Text("User Profile")
.font(.largeTitle)
.fontWeight(.bold)
HStack(spacing: 20) {
Image(systemName: "person.circle")
.font(.system(size: 50))
.foregroundColor(.blue)
VStack(alignment: .leading, spacing: 10) {
Text("John Doe")
.font(.headline)
Text("iOS Developer")
.font(.subheadline)
.foregroundColor(.gray)
}
}
ZStack {
RoundedRectangle(cornerRadius: 10)
.fill(Color.green)
.frame(height: 50)
Text("Follow")
.font(.headline)
.foregroundColor(.white)
}
.padding(.horizontal)
}
.padding()
}
}
- VStack: The main layout is vertical.
- HStack: Profile picture and details are stacked horizontally.
- ZStack: Text is placed on top of a rounded rectangle for button design.
Aligning and Customizing Stacks
struct ContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text("SwiftUI")
.font(.headline)
Text("Declarative UI Framework")
.font(.subheadline)
.foregroundColor(.gray)
}
.padding()
}
}
alignment: .leading: Content ko left-align karta hai.
Buttons and Actions in SwiftUI
The buttons and toggles in SwiftUI are very powerful and easy-to-use. You can customize them to make them visually appealing and interactive. Let’s explore how to create buttons and toggles with actions, styles, and more.
Designing Buttons
SwiftUI Button view provides a tappable interface that performs actions.
import SwiftUI
struct ContentView: View {
var body: some View {
Button("Tap Me") {
print("Button tapped!")
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
- Button(“Tap Me”): Creates a tappable button.
- action: When the button is tapped, the print statement is executed.
- background, foregroundColor, and cornerRadius: Style the button.
Customizing Buttons with Labels
You can customize the buttons with a combination of icons and text.
struct ContentView: View {
var body: some View {
Button(action: {
print("Button with icon tapped!")
}) {
HStack {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("Favorite")
.fontWeight(.bold)
}
}
.padding()
.background(Color.black)
.foregroundColor(.white)
.cornerRadius(8)
}
}
Designing Toggles
A toggle acts like an on/off switch that manages a state.
struct ContentView: View {
@State private var isOn: Bool = false
var body: some View {
Toggle(isOn: $isOn) {
Text("Enable Notifications")
}
.padding()
}
}
@state: Manages the current state(s) of the toggle.
$state: Provides bindings that modify the state of the toggle.
Customizing Toggle Styles
You can customize the toggles visually.
struct ContentView: View {
@State private var isOn: Bool = true
var body: some View {
Toggle(isOn: $isOn) {
Text(isOn ? "Notifications Enabled" : "Notifications Disabled")
.fontWeight(.bold)
.foregroundColor(isOn ? .green : .red)
}
.toggleStyle(SwitchToggleStyle(tint: .blue))
.padding()
}
}
SwitchToggleStyle: Makes the Toggle
appear in a switch-style.
tint: Sets the active color of the Toggle
.
Combining Buttons and Toggles
You can create interactive objects by combining buttons and toggles in a layout.
struct ContentView: View {
@State private var isDarkMode: Bool = false
var body: some View {
VStack(spacing: 20) {
Toggle(isOn: $isDarkMode) {
Text("Dark Mode")
.fontWeight(.bold)
}
.toggleStyle(SwitchToggleStyle(tint: .purple))
Button(action: {
print("Dark Mode is \(isDarkMode ? "Enabled" : "Disabled")")
}) {
Text("Confirm")
.padding()
.frame(maxWidth: .infinity)
.background(isDarkMode ? Color.black : Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
.padding()
}
}
- Toggle: Enables/disables dark mode.
- Button: Performs action according to the state of the toggle.
- isDarkMode: Controls the color of the toggle and button.
Handling Text and Images
Text and Image views in SwiftUI are very powerful and flexible. You can customize them in your UI to create visually appealing designs. Here we will look at: Text styling for different use cases.
Techniques to display and scale images.
Let’s get started!
Styling Text for Different Use Cases
SwiftUI text view is used to display content, and you can style it using modifiers.
Basic Text Styling
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Welcome to SwiftUI")
.font(.largeTitle) // Set the font size
.fontWeight(.bold) // Bold text weight
.foregroundColor(.blue) // Set the text colour
.padding() // Add space on 4 sides of text
}
}
Custom Font and Alignment
struct ContentView: View {
var body: some View {
Text("SwiftUI makes UI development fun!")
.font(.custom("Courier", size: 20)) // Use Custom Font
.multilineTextAlignment(.center) // Align Text in Center
.lineSpacing(10) // Increase the line spacing
.padding()
}
}
Displaying and Scaling Images with Image
SwiftUi Image View is used to display images. You can use system images or your own custom images.
struct ContentView: View {
var body: some View {
Image(systemName: "star.fill")
.font(.largeTitle) // Icon size set
.foregroundColor(.yellow) // Set Icon color
}
}
Combining Text and Images
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
Image("profile")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.clipShape(Circle()) // Image ko circle shape mein dikhayein
.overlay(
Circle().stroke(Color.blue, lineWidth: 4) // Circle border add karein
)
Text("John Doe")
.font(.headline)
.fontWeight(.bold)
Text("iOS Developer")
.font(.subheadline)
.foregroundColor(.gray)
}
.padding()
}
}
- ClipShape(circle()): Displays the image in a circular shape.
- Overlay: Places a border over the circle.
- Text: Aligns text and image vertically.
Advanced Image Scaling Techniques
struct ContentView: View {
var body: some View {
ZStack {
Image("landscape")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 300)
.clipped()
LinearGradient(
gradient: Gradient(colors: [.black.opacity(0.6), .clear]),
startPoint: .bottom,
endPoint: .top
)
Text("Explore the World")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white)
.padding()
}
}
}
- LinearGradient: Adds a gradient overlay on top of an image.
- ZStack: Stacks the gradient and text on top of an image.
Building Lists and Grids
In SwiftUI, structured data can be easily displayed using Lists and Grids. Here we will see:
Use List to display structured data.
Use LazyVGrid and LazyHGrid to create grid layouts.
Let’s understand step-by-step!
Using List to Display Structured Data
SwiftUI ListView creates a vertically scrolling list that can display dynamic or static content.
import SwiftUI
struct ContentView: View {
var body: some View {
List {
Text("Swift")
Text("Kotlin")
Text("Python")
Text("Java")
}
}
}
List: Creates a scrollable list.
Each text represents an individual list item.
Dynamic List with Data
struct ContentView: View {
let programmingLanguages = ["Swift", "Kotlin", "Python", "Java"]
var body: some View {
List(programmingLanguages, id: \.self) { language in
Text(language)
}
}
}
- List(data, id: .self): Creates a dynamic list with the data source.
- language in: Displays each item in the ProgrammingLanguages array.
List with Custom Rows
struct ContentView: View {
struct Language: Identifiable {
let id = UUID()
let name: String
let proficiency: String
}
let languages = [
Language(name: "Swift", proficiency: "Advanced"),
Language(name: "Python", proficiency: "Intermediate"),
Language(name: "Java", proficiency: "Beginner")
]
var body: some View {
List(languages) { language in
HStack {
Text(language.name)
.font(.headline)
Spacer()
Text(language.proficiency)
.foregroundColor(.gray)
}
}
}
}
- Identifiable: Each item has to be uniquely identifiable.
- Manual: Arranges multiple items horizontally in a row.
Working with LazyVGrid and LazyHGrid for Grid Layouts
It is quite efficient to create SwiftUI grids with LazyVGrid and LazyHGrid. These grids load content lazily, which is better for performance.
struct ContentView: View {
let items = Array(1...20)
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(items, id: \.self) { item in
Text("\(item)")
.frame(width: 50, height: 50)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
.padding()
}
}
}
- LazyVGrid: Creates a vertical grid layout.
- GridItem(.flexible()): Keeps the size of each column flexible.
- ForEach: Iterates items in the grid.
- ScrollView: Creates a scrollable grid.
Combining Lists and Grids
You can create complex layouts by combining lists and grids on the same screen.
struct ContentView: View {
let gridItems = [
GridItem(.adaptive(minimum: 50))
]
var body: some View {
List {
ForEach(1...5, id: \.self) { section in
Section(header: Text("Section \(section)").font(.headline)) {
LazyVGrid(columns: gridItems, spacing: 10) {
ForEach(1...10, id: \.self) { item in
Text("\(item)")
.frame(width: 50, height: 50)
.background(Color.orange)
.cornerRadius(8)
}
}
}
}
}
}
}
- Section: Divides the list logically.
- LogicGrid: Creates a grid inside the list.
Leave a Reply