Create Side Menu in SwiftUI 2.0 Like A Professional

Abdihakin Elmi
5 min readJan 5, 2021

You can also read this article in my techxposer blog website using the link below. https://techxposer.net/?p=551

in this article we are going to create side menu feature using SwiftUI 2.0. we are going to add really cool animation and i’m going to show you how to create a menu with what ever list of options you want and we are going to create a scalable solution so that you can add or remove options or change the icons or the name very easily and we are also going to implement an awesome feature where i’m going to show you how to navigate to a new screen and perform an action when navigation item is clicked.

now open xcode and create an ios project.

now we are going to create navigation view and some sort of bar button on the left.

  1. add a NavigationView to your text and then wrap the text inside a ZStack
  2. 2. now let’s add the navigation bar a button. now find where the ZStack ends and add

NavigationView {

ZStack{

Color.white

Text(“Hello world”)

}

.navigationBarItems(leading: Button{

print(“DEBUG: show menu here..”)

}label: {

Image(systemName: “list.bullet”)

.foregroundColor(.black)

})

}

I highly recommend downloading this SFSymbols application it has a giant repository of all the system images we now get provided with from xcode.

With over 2,400 configurable symbols, SF Symbols is designed to integrate seamlessly with San Francisco, the system font for Apple platforms. Each symbol comes in a wide range of weights and scales that automatically align with text labels, and supports Dynamic Type and the Bold Text accessibility feature. You can also export symbols and edit them in vector graphics editing tools to create custom symbols with shared design characteristics and accessibility features.

basically what color.white does it gives the whole screen a white background color. and it is going to be important for our side menu.

3. now let’s create our views and model for our app.

create the following SwiftUIViews and give the following names

- SideMenuView

-SideMenuHeaderView

-SideMenuOptionView

create Swift file give this name

  • SideMenuViewModel

open SideMenuView, add Zstack and add a linearGradiant Background like the image above.

in order to get it to expand up into the safe areas we are going to add a modifier called .ignoresSafeArea()

inside the overall container add a VStack. the VStack allows us to see all of our items in a vertical way

now let’s open our SideMenuHeaderView file and we are going to start with the image of the user, his name and username.

ZStack(alignment: .topTrailing) {

Button {

withAnimation(.spring()){

isShowing.toggle()

}

}label:{

Image(systemName: “xmark”).frame(width: 24, height: 24, alignment: .center).foregroundColor(.white).padding()

}

VStack(alignment: .leading) {

Button {

print(“”)

}label: {

Image(systemName: “person.circle”).resizable().frame(width: 64, height: 64, alignment: .center)

}.accentColor(.white)

Text(“Abdihakin Elmi”).font(.title).foregroundColor(.white)

Text(“@Elmi”).foregroundColor(.white).padding(.bottom, 24)

HStack(spacing: 12){

HStack(spacing: 10){

Text(“270”).bold()

Text(“Following”)

}

HStack(spacing: 10){

Text(“1,290”).bold()

Text(“Followers”)

}

Spacer()

}.foregroundColor(.white)

Spacer()

}.padding()

now before we go back to our contentView let’s open our SideMenuOptionView and modify it.

import SwiftUI

struct SMOptionsView: View {

var options: SMModel

var body: some View {

HStack(){

Image(systemName: options.imageName).resizable().frame(width: 24, height: 24, alignment: .center)

Text(options.title).font(.system(size: 15, weight: .semibold))

Spacer()

}.foregroundColor(.white).padding(.leading, 16).padding(.bottom, 10)

}

}

in the above code what we simply added is an image for our options and the option name.

now go back to the contentView and add the SideMenuHeader and SideMenuOption files.

//

// ContentView.swift

// SideMenu

//

// Created by Abdihakin Elmi on 12/29/20.

//

import SwiftUI

struct ContentView: View {

@State var isShowing = false

var body: some View {

NavigationView {

ZStack{

if isShowing {

SMView(isShowing: $isShowing)

}

HomeView()

.cornerRadius(isShowing ? 20 : 0)

.offset(x: isShowing ? 300 : 0, y: isShowing ? 44 : 0)

.scaleEffect(isShowing ? 0.8 : 1)

.navigationBarItems(leading: Button{

withAnimation(.spring()){

isShowing.toggle()

}

}label:{

Image(systemName: “list.bullet”).accentColor(.black)

}).navigationTitle(“Home”)

}.onAppear{

isShowing = false

}

}

}

}

struct ContentView_Previews: PreviewProvider {

static var previews: some View {

ContentView()

}

}

struct HomeView: View {

var body: some View {

ZStack {

Color.white

Text(“Hello World”).padding()

}

}

}

what @State property does is it listens for change if the menu is open or not.

now create the model for the options

open SideMenuOptionModelView and add the following code.

//

// SMModel.swift

// SideMenu

//

// Created by Abdihakin Elmi on 12/29/20.

//

import Foundation

enum SMModel: Int, CaseIterable {

case Profile

case Lists

case Bookmarks

case messages

case notifications

case logout

var title: String {

switch self {

case .Profile:

return “Profile”

case .Lists:

return “Lists”

case .Bookmarks:

return “Bookmarks”

case .messages:

return “messages”

case .notifications:

return “notifications”

case .logout:

return “logout”

}

}

var imageName: String {

switch self {

case .Profile:

return “person”

case .Lists:

return “list.star”

case .Bookmarks:

return “bookmark”

case .messages:

return “message”

case .notifications:

return “bell”

case .logout:

return “arrow.left.square”

}

}

}

now open SideMenuView and add @Binding property to listen for change

//

// SMHeaderView.swift

// SideMenu

//

// Created by Abdihakin Elmi on 12/29/20.

//

import SwiftUI

struct SMView: View {

@Binding var isShowing: Bool

var body: some View {

ZStack {

LinearGradient(gradient: Gradient(colors: [Color.blue, Color.purple]), startPoint: .top, endPoint: .bottom)

.ignoresSafeArea()

VStack{

//header

SMHeaderView(isShowing: $isShowing)

.frame(height: 240)

ForEach(SMModel.allCases, id: \.self){ option in

NavigationLink(

destination: Text(option.title),

label: {

SMOptionsView(options: option)

})

}

Spacer()

}.navigationBarHidden(true)

}

}

}

also add @binding property into the SideMenuHeader file

//

// SMView.swift

// SideMenu

//

// Created by Abdihakin Elmi on 12/29/20.

//

import SwiftUI

struct SMHeaderView: View {

@Binding var isShowing: Bool

var body: some View {

ZStack(alignment: .topTrailing) {

Button {

withAnimation(.spring()){

isShowing.toggle()

}

}label:{

Image(systemName: “xmark”).frame(width: 24, height: 24, alignment: .center).foregroundColor(.white).padding()

}

VStack(alignment: .leading) {

Button {

print(“”)

}label: {

Image(systemName: “person.circle”).resizable().frame(width: 64, height: 64, alignment: .center)

}.accentColor(.white)

Text(“Abdihakin Elmi”).font(.title).foregroundColor(.white)

Text(“@Elmi”).foregroundColor(.white).padding(.bottom, 24)

HStack(spacing: 12){

HStack(spacing: 10){

Text(“270”).bold()

Text(“Following”)

}

HStack(spacing: 10){

Text(“1,290”).bold()

Text(“Followers”)

}

Spacer()

}.foregroundColor(.white)

Spacer()

}.padding()

}

}

}

there you have your Side Menu bar

you can find the source code here

--

--