Create Consistent SwiftUI Designs
Written by Team Kodeco
When developing your SwiftUI application, you might want to ensure a consistent look and feel across different views and UI elements. One common element that can disrupt this consistency is an image or icon that stands out due to its color. Thankfully, SwiftUI provides an elegant solution to this problem: the template
rendering mode.
The renderingMode
view modifier in SwiftUI determines how an image should be displayed in your views. There are two rendering modes available: original
and template
. original
keeps the image’s original color, while template
discards color information and draws only the shape of the image. The color of a template image is then determined by the tint color in its environment.
Let’s look at an example. Suppose you’ve created a custom icon that you want to change color based on whether it’s selected. You could use the .template
rendering mode to achieve this.
import SwiftUI
struct ContentView: View {
@State private var isSelected = false
var body: some View {
Button(action: {
isSelected.toggle()
}) {
Image("TransparentHedgy")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
.foregroundColor(isSelected ? .brown : .gray)
}
}
}
Note: If you want to try out the examples, you can download an archive of all the images used in this section here.
The preview should look as follows:
In this code, you define a Button
that displays your custom image. The isSelected
state property determines the color of the image: brown if selected, and gray otherwise. The magic happens with .renderingMode(.template)
, which tells SwiftUI to treat the image as a shape and apply the color set with foregroundColor
.
Another advantage of using template
rendering mode is that it adapts to the color scheme of the device. This could be useful when you want your UI to seamlessly transition between light and dark appearance.
Using Template Rendering Mode With Animation
Animations offer another fun way to use template
rendering mode. By using .template
mode, you can animate the color of an image over time, creating interesting effects.
In the following example, you use animation to change the color of your custom image between purple and gray:
struct ContentView: View {
@State private var changeColor = false
var body: some View {
Image("TransparentHedgy")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
.foregroundColor(changeColor ? .purple : .gray)
.onAppear {
withAnimation(.easeInOut(duration: 2).repeatForever(autoreverses: true)) {
changeColor.toggle()
}
}
}
}
The preview should look as follows:
Here’s what this code does:
-
@State private var changeColor = false
declares a property calledchangeColor
as a@State
property wrapper. The@State
wrapper allows the view to have mutable state. ThechangeColor
property is initially set tofalse
. -
Image("TransparentHedgy")
displays an image in the view. It assumes that there is an image named TransparentHedgy included in the asset catalog of your project. -
.renderingMode(.template)
sets the rendering mode of the image to.template
. This mode allows you to change the color of the image using theforegroundColor
modifier. -
.resizable()
makes the image resizable, allowing it to scale up or down based on the frame you set. -
.aspectRatio(contentMode: .fit)
: This modifier sets the aspect ratio of the image and ensures that it fits within the available space. The.fit
content mode maintains the image’s aspect ratio while fitting it within the frame, without cropping or distorting the image. -
.frame(width: 200, height: 200)
sets the size of the image’s frame. In this example, the image is given a width and height of 200 points. -
.foregroundColor(changeColor ? .purple : .gray)
sets the color of the image. WhenchangeColor
istrue
, the image color is set to.purple
, and whenchangeColor
isfalse
, the color is set to.gray
. ThechangeColor
property is toggled in the followingonAppear
block. -
.onAppear { }
executes a closure when the view appears on the screen. -
withAnimation(.easeInOut(duration: 2).repeatForever(autoreverses: true))
wraps the animation settings for the following closure. It specifies an animation with ease-in and ease-out timing, a duration of 2 seconds and autoreversing behavior. -
changeColor.toggle()
switches the value ofchangeColor
back and forth. When the view appears, the closure is executed in an animated loop, causingchangeColor
to alternate betweentrue
andfalse
. This toggling ofchangeColor
triggers the change in the image’s color, animating it between purple and gray.
By combining these modifiers and the @State
property, the code displays an image that is resizable, has a fixed width and height of 200 points and alternates its color between purple and gray in an animated loop.
Remember, the template
rendering mode can be very useful, but it is not always the correct choice. If you have a colorful image that should always be displayed in its original colors, then you should use original
.