【问题标题】:Custom NavigationView top bar自定义 NavigationView 顶栏
【发布时间】:2021-03-12 13:54:35
【问题描述】:

我想创建一个类似于上图的设计。为了创建底部的 TabView,我使用了以下代码:

import SwiftUI

struct ParentTabView: View {

    var body: some View {
    
        TabView {
            HomeView()
                .tabItem {
                    Image(systemName: "star.fill")
                    Text("Home")
                }
            Text("Second Tab")
                .tabItem {
                    Image(systemName: "star.fill")
                    Text("Discover")
                }
            Text("Third Tab")
                .tabItem {
                    Image(systemName: "star.fill")
                    Text("Settings")
                }
        }
    }
}

和主视图

struct HomeView: View {
    var body: some View {
        NavigationView {
            Text("Home")
                .navigationBarItems(
                    trailing:
                        Button(action: {
                        }) {
                            Image(systemName: "plus")
                        }
                )
                .navigationTitle("Home")
        }
    }
}

我遇到的问题是顶部导航栏,因为我无法编辑 NavigationView 以接收标题下方的其他视图。我可以设置标题并添加“加号”按钮,但不能编辑整个顶栏。

可以以这种方式自定义 NavigationView,如果不能,我如何在保持 NavigationView 提供的优势(例如 NavigationLinks 等)的同时实现该结果。

【问题讨论】:

    标签: ios swift swiftui swiftui-navigationview


    【解决方案1】:

    Apple 提供的 NavigationBar 不能完全自定义。您可能希望为此用例创建自定义导航栏。

    幸运的是,我有一些时间,所以我创建了一个简单的可重复使用的导航栏,看起来像您想要的结果,请看下面。

    您必须隐藏 Apple 的导航栏,并将自定义导航栏作为覆盖添加到您的导航视图(如下图所示):

    这是可重用自定义导航视图的代码:

    enum CustomNavigationBarItem: String, CaseIterable {
        case dashboard = "Dashboard"
        case feed = "Feed"
        case followers = "Followers"
    }
    
    struct CustomNavigationBar: View {
        var title: String
        var items: [CustomNavigationBarItem]
        @Binding var selectedItem: CustomNavigationBarItem
        var buttonAction: () -> ()
    
        var body: some View {
            VStack {
                VStack(spacing: 10) {
                    CustomNavigationBarHeader(title: title, buttonAction: buttonAction)
                    
                    HStack(spacing: 0) {
                        ForEach(items, id: \.self) { item in
                            CustomNavigationBarItemView(text: item.rawValue, isSelected: selectedItem == item)
                                .onTapGesture {
                                    selectedItem = item
                                }
                        }
                    }
                }
                .background(Color(#colorLiteral(red: 0.1036974415, green: 0.1036974415, blue: 0.1036974415, alpha: 1)).edgesIgnoringSafeArea(.all))
                
                Spacer()
            }
        }
    }
    
    struct CustomNavigationBarItemView: View {
        var text: String
        var isSelected: Bool
        
        var body: some View {
            Text(text)
                .foregroundColor(isSelected ? .blue : Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
                .frame(maxWidth: .infinity)
                .padding(.vertical, 10)
                .padding(.horizontal, 6)
                .overlay(
                    VStack {
                        Spacer()
                        Color.blue
                            .frame(height: 2)
                            .opacity(isSelected ? 1 : 0)
                            .animation(.default)
                    }
                )
        }
    }
    
    struct CustomNavigationBarHeader: View {
        var title: String
        var buttonAction: () -> ()
        
        var body: some View {
            HStack {
                Text(title)
                    .font(.title)
                    .bold()
                
                Spacer()
                Button(action: buttonAction, label: {
                    Image(systemName: "plus")
                })
                .font(.headline)
            }
            .padding(.horizontal)
        }
    }
    

    首页查看代码:

    struct HomeView: View {
        @State private var selectedNavigationBarItem: CustomNavigationBarItem = .dashboard
        @State private var numPlusButtonClicked: Int = 0
        
        var body: some View {
            NavigationView {
                VStack {
                    Text("Home")
                        
                    switch selectedNavigationBarItem {
                        case .dashboard:
                            Text("Currently Showing: Dashboard") //Use your view here
                        case .feed:
                            Text("Currently Showing: Feed") //Use your view here
                        case .followers:
                            Text("Currently Showing: Followers") //Use your views here
                    }
                    
                    Text("Plus Button Clicked \(numPlusButtonClicked) times.")
                }
            }
            .navigationBarHidden(true)
            .overlay(
                CustomNavigationBar(title: "Home",
                                    items: [.dashboard, .feed, .followers],
                                    selectedItem: $selectedNavigationBarItem) {
                    numPlusButtonClicked += 1 // Code executed when the "+" button gets called
                }
            )
        }
    }
    

    注意事项:

    1. 您可以向“CustomNavigationBarItem”枚举添加更多项目
    2. 这绝不是一个完美的组件,因此请随意修改它以满足您的需求:D

    祝你好运!

    编辑:为 HomeView 添加代码

    【讨论】:

    • 这太不可思议了。我感激不尽!
    • 不客气!我很高兴你喜欢它。我已经更新了我的答案以包含 HomeView 的代码
    猜你喜欢
    • 1970-01-01
    • 2021-11-18
    • 2019-10-27
    • 2015-08-18
    • 2014-12-21
    • 1970-01-01
    • 2020-01-31
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多