自定义 NavigationView 顶部栏
Custom NavigationView top bar
我想创建一个类似于上图的设计。为了创建底部的 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 等)的同时实现该结果。
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
}
)
}
}
备注:
- 您可以向“CustomNavigationBarItem”枚举添加更多项目
- 这绝不是一个完美的组件,所以请随意修改它以满足您的需要:D
祝你好运!
编辑:为 HomeView 添加了代码
我想创建一个类似于上图的设计。为了创建底部的 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 等)的同时实现该结果。
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
}
)
}
}
备注:
- 您可以向“CustomNavigationBarItem”枚举添加更多项目
- 这绝不是一个完美的组件,所以请随意修改它以满足您的需要:D
祝你好运!
编辑:为 HomeView 添加了代码