Custom modifiers using ViewModifier in SwiftUI


In SwiftUI, we use modifiers, such as padding(), background(), cornerRadius(), font() and so on. These are built-in modifiers of SwiftUI that already come from the system.

There is a wide range of modifiers available to work with. Well, it is also possible to build our custom modifiers to perform some specific task. We have to use ViewModifier protocol that can perform this task.

In order to make a custom modifier, you have to create a struct that conforms to the ViewModifier protocol. There is a requirement that is defining a method with the method name body that accepts whatever content it’s being given to work with and returns some View.

There may be needed to create multiple buttons with the same style using some of the built-in modifiers to maintain the theme color of the app. But to achieve it you have to provide the modifiers again and again.

Do you not think it causes writing some code multiple times and is also a time-consuming task? Don’t worry. Many other developers also think in the same way. In this situation ViewModifier can help you to prevent using these repeating modifiers for every button you have in SwiftUI.

Below is how we can create our custom ViewModifier:

struct ButtonModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(.blue)
            .foregroundColor(.white)
            .cornerRadius(16)
    }
}

It can be seen in the above program, we have created a new struct ButtonModifier that conforms to the ViewModifier protocol. It has a method body that takes content and returns the view.

We have now able to create our custom modifier using ViewModifier. The struct just created above is our custom modifiers.

Now it’s time to use it. You can apply it to our button using modifier() modifier and pass our ViewModifier we just created. Below is how we can do it:

        Button(action: {
              // Some code
            }) {
              Text("Press me")
            }
            .modifier(ButtonModifier())

As you can see, we have assigned our ViewModifier to the button with the given code:

modifier(ButtonModifier())

As you can see, it needs to provide the structure to the modifier().

Complete code

Below is given a complete code where we have created a ViewModifier and then applied it to our button:

import SwiftUI

struct ButtonModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(.blue)
            .foregroundColor(.white)
            .cornerRadius(16)
    }
}



struct ContentView: View {
    
    var body: some View {
        
        Button(action: {
              // Some code
            }) {
              Text("Press me")
            }
            .modifier(ButtonModifier())
          
    }
    
}


In this example, we just have one button. But for only one button, doing this effort doesn’t make any sense. You may think what the hell is going on, it needs to write even less code without creating any struct.

Please let me explain before you come to a decision…

The real use of a custom modifier comes when there are multiple buttons with the same styles created in our app. With just only a single button, obviously, it looks much more code and takes some more time. But with multiple buttons, it will be the reason to decrease the time.

If we have to make some changes in all the buttons, then we only have to modify them inside the ButtonModifier struct.

ViewModifier applying to multiple buttons

In the example below, you can see a ViewModifer created and then applied to multiple buttons:

import SwiftUI

struct GreenButton: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(.green)
            .foregroundColor(.white)
    }
}



struct ContentView: View {
    
    var body: some View {
        
        Button(action: {
              // Some code
            }) {
              Text("Button 1")
            }
            .modifier(GreenButton())
        
        Button(action: {
              // Some code
            }) {
              Text("Button 2")
            }
            .modifier(GreenButton())
        
        Button(action: {
              // Some code
            }) {
              Text("Button 3")
            }
            .modifier(GreenButton())
        
        Button(action: {
              // Some code
            }) {
              Text("Button 4")
            }
            .modifier(GreenButton())
          
    }
    
}

Below is the result of the above code:

Buttons

As you can see in the above example, we have created a struct with the name GreenButton that conforms to ViewModifier. In this struct, we have provided the required modifiers to create buttons with green colors.

You can see, only providing the modifier name GreenButton applies the style to our button. In this way, we have to write the code only once and can use it for multiple buttons.

Example of applying ViewModifier to a Text view

In the given example, we create a ViewModifier with the struct name TitleText:

struct Titletext: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.system(size: 34))
            .foregroundColor(.white)
            .padding()
            .background(.purple)
    }
}

Now applying it to our Text view:

        Text("Hello World")
            .modifier( Titletext() )

Conclusion

As you can see how ViewModifier can help us by reducing the amount of code we write. As we mentioned earlier in this article, making changes only in the struct will be applied to all the views where using it. These are the greatest advantages of using view modifiers.

It helps us to create our very own custom modifier in SwiftUI. We can apply it to any view that we want and where we need it.