Please help me, I am a novice developer
I can't understand why it doesn't work for me TabView.
I did everything through a custom CustomTabButton.
It turns out that when you start the simulator tabItem is not displayed, if you run everything without a custom menu , then everything works
import SwiftUI
struct ContentView: View {
var body: some View {
MainView()
}
}
#Preview {
ContentView()
}
struct MainView: View {
// Текущая вкладка.
@State var currentTab: String = "Данные по ТО"
// Пункт меню..
@State var showMenu: Bool = false
// Скрытие собственной панели вкладок.
init() {
UITabBar.appearance().isHidden = true
}
var body: some View {
ZStack{
// Пользовательское боковое меню.
SideMenu(currentTab: $currentTab)
// Просмотр главной вкладки.
CustemTabView(currentTab: $currentTab, showMenu: $showMenu)
// Задаем радиус угла.
.cornerRadius(showMenu ? 25 : 0)
// Выполнение 3D-вращения.
.rotation3DEffect(.init(degrees: showMenu ? -15 : 0), axis: (x: 0, y: 1, z: 0),anchor: .trailing)
// Раздвигающий вид.
.offset(x: showMenu ? getRect().width / 1.7 : 0)
.ignoresSafeArea()
}
// Всегда темный режим.
.preferredColorScheme(.dark)
}
}
#Preview {
ContentView()
}
extension View {
func getSafeArea() -> UIEdgeInsets {
guard let screen =
UIApplication.shared.connectedScenes.first as?
UIWindowScene else {
return .zero
}
guard let safeArea = screen.windows.first?.safeAreaInsets
else {
return.zero
}
return safeArea
}
}
struct SideMenu: View {
@Binding var currentTab: String
// Добавление плавного перехода между вкладками с помощью
// Эффекта подобранной геометрии.
@Namespace var animation
var body: some View {
VStack {
HStack(spacing: 15) {
Image(systemName: "car.fill")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 40, height: 40)
//.clipShape(Circle())
Text("Автопомошник")
.font(.title2.bold())
.foregroundStyle(.white)
}
.padding()
.frame(maxWidth: .infinity,alignment: .leading)
//Для небольших экранов
ScrollView(getRect().height < 750 ? .vertical :
.init(), showsIndicators: false, content: {
// Кнопки вкладок
VStack(alignment: .leading, spacing: 25) {
CustomTabButton(icon: "oilcan.fill", title:
"Данные по ТО")
CustomTabButton(icon: "dollarsign", title:
"Журнал расходов")
CustomTabButton(icon: "map.fill", title:
"Дорожная кaрта")
CustomTabButton(icon: "photo", title:
"Заказ наряды")
CustomTabButton(icon: "calendar", title:
"Заметки по авто")
}
.padding()
.padding(.top,45)
})
// Ширина оси равна ширине экрана.
.frame(width: getRect ().width / 1,alignment: .leading)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.leading,10)
.frame(maxWidth: .infinity, maxHeight: .infinity,
alignment: .top)
.background(
Color(.gray)
//.ignoresSafeArea()
)
}
// Пользовательская кнопка.
@ViewBuilder
func CustomTabButton(icon: String,title: String) -> some View {
Button {
withAnimation{
currentTab = title
}
} label: {
HStack(spacing: 12){
Image(systemName: icon)
.font(.title3)
.frame(width: currentTab == title ? 48 : nil, height: 48)
.foregroundColor (currentTab == title ? Color("Lazur") : .white)
.background(
ZStack {
if currentTab == title {
Color.white
.clipShape(Circle())
.matchedGeometryEffect(id:
"TABCIRCLE", in:
animation)
}
}
)
Text(title)
.font(.callout)
.fontWeight(.semibold)
.foregroundStyle(.white)
}
.padding(.trailing,28)
.background(
ZStack{
if currentTab == title{
Color("Lazur")
.clipShape(Capsule())
.matchedGeometryEffect(id:
"TABCAPSULE", in:
animation)
}
}
)
}
.offset(x: currentTab == title ? 15 : 0)
}
}
#Preview {
ContentView()
}
// Расширяем вид, чтобы получить границы экрана.
extension View{
func getRect () -> CGRect {
return UIScreen.main.bounds
}
}
struct CustemTabView: View {
@Binding var currentTab: String
@Binding var showMenu: Bool
var body: some View {
VStack {
// Статический просмотр заголовка для всех страниц.
HStack {
// Кнопка меню.
Button {
// Переключение пункта меню
withAnimation(.spring()){
showMenu = true
}
} label: {
Image(systemName:"line.3.horizontal.decrease")
.font(.title)
.foregroundColor(.white)
}
// Скрытие при отображении меню
.opacity(showMenu ? 0 : 1)
Spacer()
}
// Заголовок страницы.
.overlay(
Text(currentTab)
.font(.title.bold())
.foregroundColor(.white)
// Такое же скрытие, когда видно меню...
.opacity(showMenu ? 0 : 1)
)
.padding([.horizontal,.top])
.padding(.bottom, 8)
.padding(.top, getSafeArea().top)
TabView(selection: $currentTab) {
MaintenanceDataView()
.tag("Данные по ТО")
CarExpensesView()
.tag("Журнал расходов")
NavigatView()
.tag("Дорожная кaрта")
PhotoLibryView()
.tag("Заказ наряды")
Home()
.tag("Заметки по авто")
}
}
// Отключение действий при отображении меню.
.disabled(showMenu)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay(
// Кнопка закрытия.
Button {
// Переключение пункта меню.
withAnimation(.spring()){
showMenu = false
}
} label: {
Text("открыть")
.font(.title2.bold())
.foregroundStyle(.white)
}
// Скрытие при отображении меню
.opacity(showMenu ? 1 : 0)
.padding()
.padding(.top)
,alignment: .topLeading
)
.background (
Color.black
)
}
}
#Preview {
ContentView()
}
That 's what doesn 't work for me , it doesn 't display tabItem
struct CarExpensesView: View {
// Просмотр свойств
@State private var currentTab: String = ""
var body: some View {
TabView(selection: $currentTab) {
AvtoExpensesView(currentTab: $currentTab)
.badge(2)
.tabItem {
Label("Расходы", systemImage: "creditcard.fill")
}
.tag("Расходы")
CategoriesView()
.badge(2)
.tabItem {
Label("Категории", systemImage: "list.clipboard.fill")
}
.tag("Категории")
}
}
}
#Preview {
CarExpensesView()
}