13

Given i have a view like this..

@State var tabIndex: Int = 0
           
 var body: some View {

  TabView(selection: $tabIndex)
  {
   Text("Tab 1").tabItem({
    Image(systemName: "message")
   }).tag(0)           
                
   Text("Tab 2").tabItem({
    Image(systemName: "arkit")
   }).tag(1)             
          
   Text("Tab 3").tabItem({
    Image(systemName: "battery.100")
   }).tag(2)
  }.navigationBarTitle("Tabbed View")
            
 }

This produces a view like this which is what is expected:

enter image description here

to add a navigation button to the bar i can use

 .navigationBarItems(trailing:
  Button(action: {print("Button was tapped")}) {
   Image(systemName: "plus")
    .resizable().frame(width: 20, height: 20)
  })

Which adds the button as expected

Is there any way to only add (or show) the button based on a condition?

if (self.tabIndex == 1){
  show button
}
else {
 don't show button
}
1
  • 2
    TabView embedded inside NavigationView isn't a good choice. Instead every tab in the TabView should have its own NavigationView. Like if there are three tabs, there should be three NavigationView if every tab needs their navigation hierarchy. Commented Jan 3, 2020 at 9:20

5 Answers 5

22

As .navigationBarItems will be deprecated in a future version of iOS it's better to use .toolbar(_:) View Modifier.

.toolbar {
    ToolbarItemGroup(placement: .navigationBarTrailing) {
        if tabIndex == 2 {
            // show button
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This should be the new accepted answer
No need to use AnyView as well
navigationBarTrailing isn't defined for me
17

Here is possible approach

.navigationBarItems(trailing: self.tabIndex == 1 ? 
    AnyView(self.trailingButton) : AnyView(EmptyView()))

somewhere below body

var trailingButton: some View {
  Button(action: {print("Button was tapped")}) {
   Image(systemName: "plus")
    .resizable().frame(width: 20, height: 20)
  }
}

1 Comment

I'm curious why you don't just put the button on the relevant view under it's tab? Is there a reason it needs to be on the TabView?
5

If you don't want to use AnyView, you could also use Group or Opacity too.

.navigationBarItems(trailing: Group {
  if self.tabIndex == 1 {
    Button(action: {print("Button was tapped")}) {
     Image(systemName: "plus")
      .resizable().frame(width: 20, height: 20)
    }
  }
})
.navigationBarItems(trailing: 
    Button(action: {print("Button was tapped")}) {
     Image(systemName: "plus")
      .resizable().frame(width: 20, height: 20)
    }.opacity(self.tabIndex == 1 ? 1 : 0)
)

Comments

3

I know this question has an accepted answer and I used it in my own solution but here's what I did:

var doneButton:AnyView {
    if !fromPreferences {
        return AnyView(Button(action: self.doneAction) {
            Text("Done")
        })
    }
    return AnyView(EmptyView())
}

and how I used it in the body:

.navigationBarItems(trailing: doneButton)

thanks @Asperi for the solution!

Comments

1

Here is what worked for me, even when my condition was false which resulted in nothing being returned (the bar item correctly did not show, without errors). I find it a little cleaner than squeezing in a ternary operator.

.navigationBarItems(
    trailing: Button(
        action: {
            print("My Action")
        }
    ) {
        if myBool {
            Text("My Button")
        }
    }
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.