0

I'm trying to show a navigation bar item on the right side and I got almost success, but I stuck at the last moment my navigation right button automatically move after showing the other view. Please check my code and screenshot given below.


struct NvaigationButton: View {
    @State private var showPopUpFlgInapp = false
    var body: some View {
        NavigationView {
            ZStack {
                ScrollView {
                    VStack {
                        Image("DemoImage1")
                            .resizable()
                            .aspectRatio(16/9, contentMode: .fit)
                    }
                    Spacer()
                }
            }
            .navigationBarTitle("", displayMode: .inline)
         .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            .navigationBarBackButtonHidden(true)
            .navigationBarItems(leading:
                                    Button(action: {
                                    }) {
                                        HStack {
                                            Image( "BackButtonWithColor")
                                        }},trailing:  AnyView(self.trailingButton))
        }
    }
    
    var trailingButton: some View {
        HStack {
            if showPopUpFlgInapp != true {
                Button(action: {
                    showPopUpFlgInapp = true
                }) {
                    HStack {
                        Image("ThreeDotsWithBckground")
                    }
                }
                
            }else if showPopUpFlgInapp == true {
                showFlagInAppr(showPopUpFlgInapp:$showPopUpFlgInapp,action: {
                    showPopUpFlgInapp = false
                })
            }
        }
    }
}

struct showFlagInAppr: View {
    @Binding var showPopUpFlgInapp: Bool
    var action: () -> Void
    var body: some View {
        if showPopUpFlgInapp {
            ZStack {
                VStack(alignment:.leading,spacing:30) {
                    Button(action: action, label: {
                        Text("Flag as inappropriate")
                    })
                }
            }.padding(20)
            .background(Color.init(UIColor.init(displayP3Red: 29/255, green: 33/255, blue: 33/255, alpha: 1.0)))
            .foregroundColor(.white)
            .cornerRadius(10)
        }
    }
}

Screen Shot 1

Screen Shot 2

Screen Shot 3

ios coder
  • 1
  • 4
  • 31
  • 91
Sham Dhiman
  • 1,348
  • 1
  • 21
  • 59

2 Answers2

1

Since your issue is a bug in ( Xcode Version 12.4 (12D4e) ) and we cannot do much about it, i came with a custom way for solving this issue, here:


enter image description here


import SwiftUI

struct ContentView: View {
    var body: some View {

        NvaigationButton()
        
    }
}

struct NvaigationButton: View {
    
    @State private var showPopUpFlgInapp = false
    
    var body: some View {
        
        NavigationView {
            
            ZStack {
                
                Text("Hello World!")
                
            }
            .navigationBarTitle("", displayMode: .inline)
            .edgesIgnoringSafeArea(.all)
            .navigationBarBackButtonHidden(true)
   
        }
        .trailingNavigationBarItems { trailingButton.padding() }       // <<: Apply Here!
        
    }
    
    

    var trailingButton: some View {
        HStack {
            if showPopUpFlgInapp != true {
                Button(action: {
                    showPopUpFlgInapp = true
                }) {
                    HStack {
                        Image(systemName: "star")
                    }
                }
                
            }else if showPopUpFlgInapp == true {
                showFlagInAppr(showPopUpFlgInapp:$showPopUpFlgInapp,action: {
                    showPopUpFlgInapp = false
                })
            }
        }
 
    }
}

struct showFlagInAppr: View {
    @Binding var showPopUpFlgInapp: Bool
    var action: () -> Void
    var body: some View {
        if showPopUpFlgInapp {
            ZStack {
                VStack(alignment:.leading,spacing:30) {
                    Button(action: action, label: {
                        Text("Flag as inappropriate")
                    })
                }
            }
            .padding(20)
            .background(Color.init(UIColor.init(displayP3Red: 29/255, green: 33/255, blue: 33/255, alpha: 1.0)))
            .foregroundColor(.white)
            .cornerRadius(10)
        }
    }
}

struct TrailingNavigationBarItems<InputContent: View>: ViewModifier {

    var inputContent: () -> InputContent

    func body(content: Content) -> some View {

        return content
            .overlay(inputContent(), alignment: .topTrailing)

    }
    
}


extension View {

    func trailingNavigationBarItems<InputContent: View>(_ inputContent: @escaping () -> InputContent) -> some View {

        return self.modifier(TrailingNavigationBarItems(inputContent: inputContent))

    }

}

ios coder
  • 1
  • 4
  • 31
  • 91
  • My Xcode Version 12.3 (12C33) and i will check your solution thank you for your reply @Punk – Sham Dhiman Mar 19 '21 at 08:10
  • 1
    @ShamDhiman: you are welcome, since I noticed it is a bug and your code is fine, I said we cannot just wait for apple to fix, I tried to fix it in my way. – ios coder Mar 19 '21 at 08:14
1

A possible solution is to use a toolbar instead of navigationBarItems:

struct NvaigationButton: View {
    @State private var showPopUpFlgInapp = false
    var body: some View {
        NavigationView {
            ZStack {
                ScrollView {
                    VStack {
                        Image("DemoImage1")
                            .resizable()
                            .aspectRatio(16 / 9, contentMode: .fit)
                    }
                    Spacer()
                }
            }
            .navigationBarTitle("", displayMode: .inline)
            .edgesIgnoringSafeArea(.all)
            .navigationBarBackButtonHidden(true)
            .toolbar { // <- add here
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {}) {
                        HStack {
                            Image("BackButtonWithColor")
                        }
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    trailingButton
                }
            }
        }
    }

    var trailingButton: some View {
        HStack {
            if showPopUpFlgInapp != true {
                Button(action: {
                    showPopUpFlgInapp = true
                }) {
                    HStack {
                        Image("ThreeDotsWithBckground")
                    }
                }

            } else if showPopUpFlgInapp == true {
                Text("") // this prevents `showFlagInAppr` from showing inline
                showFlagInAppr(showPopUpFlgInapp: $showPopUpFlgInapp, action: {
                    showPopUpFlgInapp = false
                })
            }
        }
    }
}

Note: with the current behaviour of the toolbar, we need to add an extra empty Text as in this answer to prevent the showFlagInAppr from showing inline.

pawello2222
  • 46,897
  • 22
  • 145
  • 209