Let's create a custom tab view in SwiftUI 2.0

API added in Swift UI 2.0

I wanted to use the PageTabViewStyle added in SwiftUI 2.0, so I created something like a custom tab.

Completed form for the time being

I would like to make something like this. 999.gif GitHub is here. https://github.com/hoshi005/custom-tab

Development environment

Advance preparation

--I'm using SDWebImageSwiftUI because I wanted to use animated gifs. -Piyokoyarou uses an animated gif file.

Creating a tab part

スクリーンショット 2020-10-21 21.12.23.png

Since the animated gif file is named and placed like this, the enum is defined by matching the names.

enum TabItem: String, CaseIterable {
    case piyo
    case pen
    case neko
    case tobipen
    
    var name: String {
        "\(self.rawValue).gif"
    }
}

I added TabItemView to represent each tab and defined it as follows.

struct TabItemView: View {
    
    let tabItem: TabItem
    @Binding var selected: TabItem
    
    var body: some View {
        //SDWebImageSwiftUI import required.
        AnimatedImage(name: tabItem.name)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 40)
            .onTapGesture {
                selected = tabItem //Tap to select yourself.
            }
    }
}

In the main ContentView, the tab view is defined as follows.

struct ContentView: View {
    
    //Tab selection and initial values.
    @State private var selected: TabItem = .piyo
    
    var body: some View {
        
        //Tab view part.
        HStack {
            ForEach(TabItem.allCases, id: \.self) { tabItem in
                TabItemView(tabItem: tabItem, selected: $selected)
            }
        }
        .padding(.vertical, 10.0)
        .padding(.horizontal, 20.0)
        .background(Color.white.clipShape(Capsule()))
        .shadow(color: Color.black.opacity(0.3), radius: 5, x: -5, y: 5)
    }
}

Here is the finished product. At this rate, you don't really understand the selection status. 001.gif

Adjust the appearance so that you can see the selected state

Rewrite TabItemView as follows to switch the appearance when selected / not selected.

--Adjust frame --Adjust padding --Adjust offset --Animation is added to the tapping process

var body: some View {
   AnimatedImage(name: tabItem.name)
       .resizable()
       .aspectRatio(contentMode: .fit)
       //Adjust the size and spacing according to the selection status.
       .frame(width: tabItem == selected ? 100 : 40)
       .padding(.vertical, tabItem == selected ? -30 : 0)
       .padding(.horizontal, tabItem == selected ? -14 : 16)
       .offset(y: tabItem == selected ? -15 : 0)
       .onTapGesture {
           withAnimation(.spring()) {
               selected = tabItem //Tap to select yourself.
           }
       }
}

It looks like this. You can now see the selection status at a glance. 002.gif

Background color setting and tab placement adjustment

Adjust the appearance of ContentView.

--Enclose the whole with ZStack --Place Color ("bg"). IgnoresSafeArea () on the back to make it the background color --Place the tab view part at the bottom of the screen using VStack and Spacer

var body: some View {
    
    ZStack {
        
        //Background color.
        Color("bg").ignoresSafeArea()
        
        VStack {
            
            Spacer(minLength: 0)
            
            //Tab view part.
            HStack {
                ForEach(TabItem.allCases, id: \.self) { tabItem in
                    TabItemView(tabItem: tabItem, selected: $selected)
                }
            }
            .padding(.vertical, 10.0)
            .padding(.horizontal, 20.0)
            .background(Color.white.clipShape(Capsule()))
            .shadow(color: Color.black.opacity(0.3), radius: 5, x: -5, y: 5)
        }
    }
}

It looks like this. It's becoming more like that. 003.gif

Switch screens with tabs

I have prepared a tab, so I will switch the screen in conjunction with this tab.

First, prepare the screen part with a dummy. It's suitable, so I think you can make it as you like.

struct HomeView: View {
    var body: some View {
        Text("Home")
            .font(.largeTitle)
            .fontWeight(.heavy)
            .foregroundColor(.red)
    }
}

struct ListView: View {
    var body: some View {
        Text("List")
            .font(.largeTitle)
            .fontWeight(.heavy)
            .foregroundColor(.green)
    }
}

struct SearchView: View {
    var body: some View {
        Text("Search")
            .font(.largeTitle)
            .fontWeight(.heavy)
            .foregroundColor(.blue)
    }
}

struct SettingView: View {
    var body: some View {
        Text("Setting")
            .font(.largeTitle)
            .fontWeight(.heavy)
            .foregroundColor(.yellow)
    }
}

Finally, define these Views with TabView to work with your custom tabs.

--By specifying selected in the argument of TabView, it works with the custom tab. --By specifying PageTabViewStyle, you can switch by swiping horizontally.

ZStack {
    
    //Background color.
    Color("bg").ignoresSafeArea()
    
    //The main screen part is defined by TabView.
    TabView(selection: $selected) {
        HomeView()
            .tag(TabItem.piyo)
        ListView()
            .tag(TabItem.pen)
        SearchView()
            .tag(TabItem.neko)
        SettingView()
            .tag(TabItem.tobipen)
    }
    //Use PageTab style(Indicator is hidden).
    .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
    
    VStack {
        //abridgement.
    }
}

Summary

I get the impression that tab definition is quite easy, but I'm happy that it's even easier to create a "switching UI". It seems that the same thing can be done with the switching view created by this article. Please try it if you like.

Recommended Posts

Let's create a custom tab view in SwiftUI 2.0
[Kotlin / Android] Create a custom view
Let's create a super-simple web framework in Java
[Java] Let's create a mod for Minecraft 1.14.4 [3. Add creative tab]
Create a database in a production environment
Create a new app in Rails
Create a Servlet program in Eclipse
Let's create a TODO application in Java 4 Implementation of posting function
Let's create a TODO application in Java 6 Implementation of search function
Let's create a TODO application in Java 8 Implementation of editing function
Let's create a TODO application in Java 1 Brief explanation of MVC
Let's create a TODO application in Java 5 Switch the display of TODO
Let's create a Java development environment (updating)
Create a TODO app in Java 7 Create Header
[Rails] Let's create a super simple Rails API
Docker Compact Manual (4: Create a custom image)
Let's create a versatile file storage (?) Operation library by abstracting file storage / acquisition in Java
Create a CSR with extended information in Java
Let's create a REST API using WildFly Swarm.
Let's create a timed process with Java Timer! !!
Create a simple batch processing framework in Eclipse.
Try to create a bulletin board in Java
[Java] Let's create a mod for Minecraft 1.14.4 [Introduction]
How to create a theme in Liferay 7 / DXP
[Java] Let's create a mod for Minecraft 1.16.1 [Introduction]
Create a tool for name identification in Salesforce
How to easily create a pull-down in Rails
[Java] Let's create a mod for Minecraft 1.14.4 [99. Mod output]
Set up a webhook in Shopify's custom app
Create a native extension of Ruby in Rust
Let's create JUnit.
Let's create a TODO application in Java 11 Exception handling when accessing TODO with a non-existent ID
[Java] Let's create a mod for Minecraft 1.14.4 [0. Basic file]
[Java] Let's create a mod for Minecraft 1.14.4 [4. Add tools]
How to create a Java environment in just 3 seconds
[Java] Let's create a mod for Minecraft 1.14.4 [5. Add armor]
Let's write a Qiita article in org-mode of Emacs !!
[Java] Let's create a mod for Minecraft 1.14.4 [Extra edition]
[Java] Let's create a mod for Minecraft 1.14.4 [7. Add progress]
[SwiftUI] Create a TextField that looks like a Qiita tag
[Java] Let's create a mod for Minecraft 1.14.4 [6. Add recipe]
[Java] Let's create a mod for Minecraft 1.16.1 [Add item]
How to create a Spring Boot project in IntelliJ
[Java] Let's create a mod for Minecraft 1.16.1 [Basic file]
If there is a state transition, let's create a State class
Let's create a gcloud development environment on a centos8 container
I tried to create a Clova skill in Java
[Java] Let's create a mod for Minecraft 1.14.4 [1. Add items]
How to create a data URI (base64) in Java
[Programming complete] §5 Create a review management app in Ruby
[Java] Let's create a mod for Minecraft 1.14.4 [2. Add block]
[Rails] How to load JavaScript in a specific view
Create a frameless non-rectangular window in JavaFX without a taskbar
[Java] Let's create a mod for Minecraft 1.16.1 [Add block]