10

I try to create a (add/plus) button that shows a menu from which we can select the action we want to execute (it is similar to the Files, or Notes app on iPhone)

.navigationTitle("Hello World Everyone")
.toolbar {
    ToolbarItem(placement: .navigationBarTrailing) {
        Menu(content: {
            Button(action: {print("option A")}, label: {Label("My option A", systemImage: "folder.badge.plus")})
            Button(action: {print("option B")}, label: {Label("My option B", systemImage: "doc.badge.plus")})
        }, label: {
            Image(systemName: "plus")
                .imageScale(.large)
                .background(Color.red)
        })
    }
}

But the issue is that it is extremely hard to tap on this "plus" button ! On the other hand if instead of the Menu block I used a traditional Button block this issue disappears (but of course I loose the functionality that I want) (in Xcode 13b4 it is no-more the case)

Do you have any ideas?

EDIT 1:

Few people recommended me to add a padding to the label of Menu, which is a good idea but here is why it is not perfect :

The tappable area (represented in red) does not go until the trailing edge of the screen (see purple drawing). So if by misfortune the user tapped on this side of the add button (purple zone), the click will not work : in other words it remains quite hard to tap on this button!
And another issue is that the plus icon is shifted on the left from his default position

LetsGoBrandon
  • 498
  • 8
  • 23
  • For me, the size, position, and everything is exactly the same when just using a regular button. Tested in iOS 15, Xcode 13b4 – George Aug 01 '21 at 21:20
  • Ohww no bad news. I just downloaded Xcode 13b4 and yes it seems like that the `Button` inside a `ToolbarTtem` will work differently : today we can click on the edge of the screen and the button is triggered, but in the beta it will not be possible anymore :/ – LetsGoBrandon Aug 01 '21 at 22:29

2 Answers2

0

If you use Button inside Toolbar SwiftUI will automatically converts it into ToolBarButton, which customisation is not possible on ToolBarButton . Instead of passing a Button you can pass a Custom View.

        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Menu(content: {
                    Label("My option A", systemImage: "folder.badge.plus")
                        .onTapGesture { 
                            print("My option A") 
                        }
                    Label("My option B", systemImage: "doc.badge.plus")
                        .onTapGesture { 
                            print("My option B") 
                        }
                }, label: {
                    Image(systemName: "plus")
                        .imageScale(.large)
                        .background(Color.red)
                })
            }
        }
Vishweshwaran
  • 149
  • 3
  • 6
  • It does not answer the question, the space between the red square and the edge of the screen doesn't trigger the "button" – LetsGoBrandon Dec 06 '22 at 17:32
  • It won't trigger since it is barButton. Instead of Button use some other View. Button on toolbar will become ToolBarButton that's the native behaviour of SwiftUI. And ToolBarButton won't have actions on the are you marked with pink color. – Vishweshwaran Dec 07 '22 at 14:37
  • But that pink area triggers the buttons on some other apps (for example the official Clock app) – LetsGoBrandon Dec 11 '22 at 21:04
  • 1
    Agreed @LetsGoBrandon. Clock app uses UIKit Component of bar button item. On that it will be native behaviour. But in SwiftUI this an bug or I don't know Apple made it in that way. But we are on the same room. We all are facing this issues as well. – Vishweshwaran Dec 13 '22 at 11:57
0

I'm not sure you can expand the buttons inside the Toolbar beyond the "safe area".

I just wanted to let you know that the actual button in this case is the Menu and not the Image in the label, so you're not highlighting the full button. See the full tapping area in green.

Also using a bigger image, like "plus.circle" gives you a bigger area.

Example image:

Example image

Example code:
.navigationBarBackButtonHidden()
.navigationTitle("Hello World Everyone")
.toolbar {
    ToolbarItemGroup(placement: .navigationBarTrailing) {
        Menu(content: {
            Button(action: {print("option A")}, label: {Label("My option A", systemImage: "folder.badge.plus")})
            Button(action: {print("option B")}, label: {Label("My option B", systemImage: "doc.badge.plus")})
        }, label: {
            Image(systemName: "plus")
                .imageScale(.large)
                .background(Color.red)
        })
        .background(Color.green)
        Menu(content: {
            Button(action: {print("option A")}, label: {Label("My option A", systemImage: "folder.badge.plus")})
            Button(action: {print("option B")}, label: {Label("My option B", systemImage: "doc.badge.plus")})
        }, label: {
            Image(systemName: "plus.circle")
                .imageScale(.large)
                .background(Color.red)
        })
        .background(Color.green)
    }
}
aone
  • 57
  • 8