Drag gesture with SwiftUI

In this post, we’ll learn how to use a drag gesture to check the scrolling direction of a list. The goal is to hide the tab bar and change the appearance of a floating button based on whether the list is scrolling up or down, similar to the behavior of the Gmail app. (Check the code from previous post floating-button-in-swiftui).

First step: Define the two different styles for the Floating Button:

struct FullFB: View {
    var body: some View {
        Label("write", systemImage: "pencil")
        .font(.title.weight(.semibold))
        .padding()
        .background(.pink)
        .foregroundStyle(.white)
        .clipShape(RoundedRectangle(cornerSize: CGSize(width: 40, height: 40)))
        .shadow(radius: 4, x: 0, y: 4)
    }
}

struct SmallFB: View {
    var body: some View {
        Image(systemName: "pencil")
        .font(.title.weight(.semibold))
        .padding()
        .background(.pink)
        .foregroundStyle(.white)
        .clipShape(Circle())
        .shadow(radius: 4, x: 0, y: 4)
    }
}

The code should be self-explanatory: the first style is a rounded rectangle button featuring both text and an icon, while the second style is a circular button with only an icon.

Now take a look to the list:

List(initList(), id:\.self) { mail in
                        HStack {
                            Text(mail)
                            Spacer()
                        }
                    }
                    .gesture(
                        DragGesture().onChanged { value in
                            if value.translation.height > 0{
                                tabbarVisibility = .visible
                            } else {
                                tabbarVisibility = .hidden
                            }
                        }
                    ).toolbar(tabbarVisibility, for: .tabBar)

We display a list of text, but we also attach a gesture to the list. When the DragGesture changes its value, we check the translation. If it’s greater than zero, the list is scrolling up, and we set the tab bar visibility to visible. In any other case, it’s set to hidden.

The complete code is:

struct ContentView: View {
    @State var tabbarVisibility: Visibility = .visible
    var body: some View {
        TabView {
            NavigationStack {
                ZStack {
                    List(initList(), id:\.self) { mail in
                        HStack {
                            Text(mail)
                            Spacer()
                        }
                    }
                    .gesture(
                        DragGesture().onChanged { value in
                            if value.translation.height > 0{
                                tabbarVisibility = .visible
                            } else {
                                tabbarVisibility = .hidden
                            }
                        }
                    ).toolbar(tabbarVisibility, for: .tabBar)
                    .padding()
                    
                    VStack {
                        Spacer()
                        HStack {
                            Spacer()
                            NavigationLink { EmptyView()} label: {
                                if tabbarVisibility == .visible {
                                    FullFB()
                                } else {
                                    SmallFB()
                                }
                                                            
                            }.padding()
                        }
                    }.padding()
                }
            }.tabItem {
                Label("Emails", systemImage: "envelope")
            }
            Text("Second tab")
            .tabItem {
                Label("Video", systemImage: "video")
            }
        }
        
    }
    func initList() -> [String] {
        var emails = [String]()
        for i in 1000000...1000100 {
            emails.append("Email " + String(i))
        }
        return emails
    }
}

The tabbarvisibility is also used to determine which type of floating button to display.

Towards coding and beyond… If you’d like to stay updated with the latest content from my blog, consider subscribing to my weekly newsletter.

Note: English is not my native language, sorry for any errors. I use ChatGPT only to generate the banner of the post, the content is human.

share this post with friends

Picture of Nicola De filippo

Nicola De filippo

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve

Leave a comment

Your email address will not be published. Required fields are marked *

Who I am

I'm a software engineer who adds to the passion for technologies the wisdom and the experience without losing the wonder for the world. I love to create new projects and to help people and teams to improve.

Follow Me Here

Get The Latest Updates

Periodically receive my super contents on coding and programming

join the family;)

Recent Posts