2021/02/01

[SwiftUI]NeumorphicなカスタムTabbarを作成しました

swiftneumorphism

実施内容

Neumorphismな見た目のカスタムTabviewを実装しました。

以下のような感じになりました。

capture-min.png

実装内容

TabItem

  • 一つのTabに当たるComponent
import SwiftUI
import Neumorphic

struct TabItem<Tab>: View where Tab: Equatable {
    let image: Image
    let tab: Tab
    var mainColor: Color = Neumorphic.shared.mainColor()
    var darkShadowColor: Color = Neumorphic.shared.darkShadowColor()
    var lightShadowColor: Color = Neumorphic.shared.lightShadowColor()
    @Binding var selected: Tab
    
    var body: some View {
        if tab == selected {
            VStack {
                image.imageScale(.large)
                    .foregroundColor(.primary)
            }
            .frame(width: 20, height: 20)
            .padding()
            .background(
                RoundedRectangle(cornerRadius: 10)
                        .fill(mainColor)
                        .softInnerShadow(
                            RoundedRectangle(cornerRadius: 10),
                            darkShadow: darkShadowColor,
                            lightShadow: lightShadowColor,
                            spread: 0.05,
                            radius: 2
                        )
            )
        } else {
            VStack {
                image.imageScale(.large)
                    .foregroundColor(.textInactive)
            }
            .frame(width: 20, height: 20)
            .padding()
            .background(
                RoundedRectangle(cornerRadius: 10)
                    .fill(mainColor)
                    .softOuterShadow()
            )
            .onTapGesture {
                selected = tab
            }
        }
    }
}

MainView

  • メイン画面
import SwiftUI
import Neumorphic


struct MainView: View {
    
    @State var selectedTab = Tab.home
    
    enum Tab: Int {
        case home, tasks, calendar, settings
    }
    
    var body: some View {
        ZStack {
            Neumorphic.shared.mainColor().ignoresSafeArea()
            TabView(selection: $selectedTab) {
                HomeView().tag(Tab.home)
                TasksView().tag(Tab.tasks)
                CalendarView().tag(Tab.calendar)
                SettingsView().tag(Tab.settings)
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            VStack {
                Spacer(minLength: 0)
                if (selectedTab != Tab.settings) {
                    // floating button
                    HStack {
                        Spacer()
                        VStack {
                            Spacer()
                            IconButton(
                                action: {},
                                image: Image(systemName: "plus")
                            )
                            .padding(EdgeInsets(top: 0, leading: 0, bottom: 16.0, trailing: 16.0))
                        }
                    }
                }
                HStack(spacing: 0) {
                    Spacer()
                    TabItem(
                        image: Image(systemName: "house"),
                        tab: Tab.home,
                        selected: $selectedTab
                    )
                    Spacer()
                    TabItem(
                        image: Image(systemName: "list.bullet"),
                        tab: Tab.tasks,
                        selected: $selectedTab
                    )
                    Spacer()
                    TabItem(
                        image: Image(systemName: "calendar"),
                        tab: Tab.calendar,
                        selected: $selectedTab
                    )
                    Spacer()
                    TabItem(
                        image: Image(systemName: "gearshape"),
                        tab: Tab.settings,
                        selected: $selectedTab
                    )
                    Spacer()
                }
                .padding(.top, 8)
                .padding(.horizontal, 8)
                .background(
                    RoundedRectangle(cornerRadius: 5).fill(Neumorphic.shared.mainColor())
                )
            }
        }
    }
}

以上です。
作業記録・備忘録でした。