iosswiftswiftuimenuitemdrawer

How to set action for open and close menubar in our iOS Application in SwiftUi?


When I tap a menu button the side menu is open, And when i drag to for open then also works properly and when click outside of menuView then does not hide the menu drawer.

This is menu View DrawerContent for navigation:

struct MenuView: View {

    var body: some View {
        ScrollView(.vertical){
        VStack {
            
            
            
            HStack{
                Image(systemName: "house")
                    .font(.title2)
                    .foregroundColor(.gray)
                   
                Spacer()
            }
            .padding(.vertical)
            
            HStack{
                Image(systemName: "square.grid.3x3.fill")
                    .font(.title2)
                    .foregroundColor(.gray)
                   
                Spacer()
            }
            .padding(.vertical)
            
            
            HStack{
                Image(systemName: "lightbulb.fill")
                    .font(.title2)
                    .foregroundColor(.gray)
                    .padding(.leading)
                    Text("Plan")
                    .font(.title2)
//                    .foregroundColor(.black)
                    .padding(.leading,5)
                Spacer()
            }
            .padding(.vertical)
         
            
            
           

        }
        .padding(.leading,35)
        .frame(width: UIScreen.main.bounds.width*0.8,alignment: .center)
        }
        
    }
}

This is Home Page for drag gesture and on TapGesture and it works great. But my mind is blank that what code I should implement:

    struct UserHomePage: View {
    // The offset variable holds the offset to show or hide the menu.
    @State private var offset = CGFloat.zero
    @State private var closeOffset = CGFloat.zero
    @State private var openOffset = CGFloat.zero
    
    var body: some View {
        // Use GeometoryReader to get the screen size
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                // Main Content
                NavigationView {
                    ZStack {
                      
                       
                       
                       
                        // Gray out the main content when the slide menu comes up
                      
                        Color.gray.opacity(
                            Double((self.closeOffset - self.offset)/self.closeOffset) - 0.1).onTapGesture {
              
                                print("Tap Gesture")
                            }
                            .ignoresSafeArea(.all)
                      
//                        }
                        FirstView()
                    }
                    .navigationBarTitle("Alibrary", displayMode: .inline)
                    .navigationBarItems(leading: Button(action: {
                            self.offset = self.openOffset
                        }){
                            Image(systemName: "line.3.horizontal")
                                .foregroundColor(.black)
                                .font(.headline)
                        }
                        )
                   
                    .edgesIgnoringSafeArea(.bottom)
                }
//                 Slide menu
                MenuView()
                    .background(Color.white)
                    .frame(width: geometry.size.width * 0.65)
                    .edgesIgnoringSafeArea(.bottom)
                    // First, minus the value of offset for the screen width for the slide menu.
                    .onAppear(perform: {
                        self.offset = geometry.size.width * -1
                        self.closeOffset = self.offset
                        self.openOffset = .zero
                    })
                    .offset(x: self.offset)
                    // Set the animation of the slide.
                    .animation(.default)
            }
            // We'll implement the gestures
            // Set swipe thresholds to prevent users from unexpectedly appearing in menus
            .gesture(DragGesture(minimumDistance: 50)
                    .onChanged{ value in
                        // Reduce the value of the offset (menu position) according to the distance swiped
                        if (self.offset < self.openOffset) {
                            self.offset = self.closeOffset + value.translation.width
                        }
                      
                      
                    }
                    .onEnded { value in
                        // If the end of the swipe is to the right of the start position, open the menu.
                        if (value.location.x > value.startLocation.x) {
                            self.offset = self.openOffset
                        } else {
                            self.offset = self.closeOffset
                        }
//                        self.offset = self.openOffset
                    }
                )
        }
    }
}

And I don't understand how to implement the code for closing menu View on click on outside of the Menu area

Please help me for design a Menu Drawer open close (for open click on button and drag gesture. and for close drag gesture And click on outside of menuView)

I am a native User of SwiftUI.


Solution

  • This is Side Menu View

     struct MenuView: View {
            
            @State var shown = false
     
            var body: some View {
                
            
                    ScrollView(.vertical){
                        
                        
                        ZStack {
                      
                            SideMeNu Items
                
                }
            }
    

    This is Main View and from here we can gesture and open and close side menu and open for drag and close for drag. and we can close the side menu on click outside of Side menu View

    struct UserAct: View {
       
        @State private var offset = CGFloat.zero
        @State private var closeOffset = CGFloat.zero
        @State private var openOffset = CGFloat.zero
        @State private var showMenu = false
    
        var body: some View {
    
            GeometryReader { geometry in
                ZStack(alignment: .leading) {
                    // Main Content
                    NavigationView {
                        ZStack {
                            VStack{
                                HStack{
                                    Button(action: {
                                        
                                        self.offset = self.openOffset
                                        
                                    }, label: {
                                        
                                        Image(systemName: "line.3.horizontal")
                                            .foregroundColor(.white)
                                            .font(.headline)
                                        
                                    })
                                    
                                    
                                    Button(action: {
                                        
                                    }, label: {
                                   
                                    
                                    ZStack {
    
                                        HStack {
                                                 
                                            if #available(iOS 16.0, *) {
                                                Image(systemName: "magnifyingglass").foregroundColor(.gray).fontWeight(.heavy)
                                            } else {
                                             
                                                
                                                Image(systemName: "magnifyingglass").foregroundColor(.gray).font(.body).frame(width: 30,height: 30)
                                            }
                                            Text("search books..").foregroundColor(.gray)
                                            Spacer()
                                                   
                                        }.frame(width: UIScreen.main.bounds.width*0.5)
                                                .padding(.leading, 7)
                                            }
                                                .frame(height: 40)
                                                .background()
                                                .cornerRadius(8)
                                    })
                                    Spacer()
                                    Button(action: {
                                        
                                        
                                        
                                        
                                        
                                    }, label: {
                                        Image("qr_c").resizable()
                                            .frame(width: 30, height: 30)
                                            
                                    })
                                
                                    Spacer()
                                    Button(action: {
                                        
                                    }, label: {
                                        Image(systemName: "ellipsis")
                                            .foregroundColor(.white)
                                            .font(.system(size: 33))
                                            .rotationEffect(.degrees(-90))
                                            .frame(width: 11, height: 55, alignment: .center)
                                            .padding()
                                            
                                    })
                                }.padding(.leading)
    
                                .frame( width: UIScreen.main.bounds.width,height: UIScreen.main.bounds.height*0.06)
                                
                                .font(.headline)
                                .background(Color.orange)
                                
                              
                                if self.offset == self.openOffset{
                                    Color.gray.opacity(0.4)
    //                                    Double((self.closeOffset - self.offset)/self.closeOffset) - 0.2).animation(.default)
                                        
                                        
                                        .onTapGesture {
                                            self.offset = self.closeOffset
    
                                         
                                        }
    
                                    
                                    
                                }
                                else{
                                    FirstView()
                           
                                }
                                
                            }
                        }.navigationBarBackButtonHidden(true)
    
                       
                        .edgesIgnoringSafeArea(.bottom)
                    }
    
                    
                    MenuView()
                            .background(Color.white)
                            .frame(width: geometry.size.width * 0.65)
                            .edgesIgnoringSafeArea(.bottom)
                         
                            .onAppear(perform: {
                                self.offset = geometry.size.width * -1
                                self.closeOffset = self.offset
                                self.openOffset = .zero
                            })
                            .offset(x: self.offset)
                          
                        .animation(.default, value: 0)
                    
                }
               
                .gesture(DragGesture(minimumDistance: 50)
                        .onChanged{ value in
                           
                            if (self.offset < self.openOffset) {
                                self.offset = self.closeOffset + value.translation.width
                            }
                          
                        }
                        .onEnded { value in
                            // If the end of the swipe is to the right of the start position, open the menu.
                            if (value.location.x > value.startLocation.x) {
                                self.offset = self.openOffset
                            } else {
                                self.offset = self.closeOffset
                            }
                            self.offset = self.openOffset
                        }
                    )
            }
        }
    }