burger menu swipe

This commit is contained in:
cheykrym 2025-08-14 02:19:09 +03:00
parent 478020f6f2
commit 05a0d85c09

View File

@ -10,8 +10,9 @@ struct MainView: View {
@State private var accounts = ["@user1", "@user2", "@user3"] @State private var accounts = ["@user1", "@user2", "@user3"]
@State private var sheetType: ProfileTab.SheetType? = nil @State private var sheetType: ProfileTab.SheetType? = nil
// Состояние для бокового меню // Состояния для бокового меню
@State private var isSideMenuPresented = false @State private var isSideMenuPresented = false
@State private var menuOffset: CGFloat = 0
private var tabTitle: String { private var tabTitle: String {
switch selectedTab { switch selectedTab {
@ -23,6 +24,10 @@ struct MainView: View {
} }
} }
private var menuWidth: CGFloat {
UIScreen.main.bounds.width * 0.8
}
var body: some View { var body: some View {
NavigationView { NavigationView {
ZStack { ZStack {
@ -61,28 +66,69 @@ struct MainView: View {
.sheet(item: $sheetType) { type in .sheet(item: $sheetType) { type in
// ... sheet presentation logic // ... sheet presentation logic
} }
// Затемнение фона при открытом меню
.background(isSideMenuPresented ? Color.black.opacity(0.4) : Color.clear) // Затемнение и закрытие по тапу
.onTapGesture {
if isSideMenuPresented { if isSideMenuPresented {
withAnimation { Color.black.opacity(0.4 + Double((menuOffset / menuWidth)))
.ignoresSafeArea()
.onTapGesture {
withAnimation(.easeInOut) {
isSideMenuPresented = false isSideMenuPresented = false
} }
} }
} }
// Боковое меню // Боковое меню
if isSideMenuPresented {
HStack {
SideMenuView(isPresented: $isSideMenuPresented) SideMenuView(isPresented: $isSideMenuPresented)
.frame(width: UIScreen.main.bounds.width * 0.8) .frame(width: menuWidth)
Spacer() .offset(x: (isSideMenuPresented ? 0 : -menuWidth) + menuOffset)
.ignoresSafeArea(edges: .vertical)
.zIndex(1)
} }
.ignoresSafeArea(edges: .vertical) // Игнорируем safe area .gesture(
.transition(.move(edge: .leading)) DragGesture()
.zIndex(1) // Убедимся, что меню поверх всего .onChanged { gesture in
// Разрешаем открывать только свайпом от левого края, а закрывать откуда угодно
if !isSideMenuPresented && gesture.startLocation.x > 60 {
return
}
let translation = gesture.translation.width
if isSideMenuPresented {
// Если меню открыто, позволяем двигать его влево до полного закрытия
let newOffset = max(-menuWidth, translation)
self.menuOffset = min(0, newOffset)
} else {
// Если меню закрыто, позволяем двигать его вправо до полного открытия
self.menuOffset = max(0, translation)
} }
} }
.onEnded { gesture in
// Если свайп был не от края (для закрытого меню), ничего не делаем
if !isSideMenuPresented && gesture.startLocation.x > 60 {
return
}
let threshold = menuWidth * 0.4
withAnimation(.easeInOut) {
if isSideMenuPresented {
// Если меню было открыто и сдвинуто влево больше, чем на `threshold`
if menuOffset < -threshold {
isSideMenuPresented = false
}
} else {
// Если меню было закрыто и сдвинуто вправо больше, чем на `threshold`
if menuOffset > threshold {
isSideMenuPresented = true
}
}
// Возвращаем временное смещение в 0, основное состояние `isSideMenuPresented` сделает остальное
self.menuOffset = 0
}
}
)
} }
.navigationViewStyle(StackNavigationViewStyle()) .navigationViewStyle(StackNavigationViewStyle())
} }