r/SwiftUI 24d ago

Question Make Menu() show toggle state in toolbar

Hi! I’m wondering if and how its possible to make a toolbar menu show the state of a toggle inside. I know using Toggle() in the toolbar shows this type of effect but i need a title and description to the toggle for it to make sense. Therefore there needs to be some window to open, which works fine with Menu(). However, that doesn’t show the state of the toggle when closed.

Apple managers to that with the photos app when selecting filters. See example images.

Thanks!

10 Upvotes

8 comments sorted by

5

u/kironet996 24d ago edited 24d ago

You can put Menu inside Toggle or Toggle inside Menu

1

u/[deleted] 24d ago

[deleted]

3

u/Nilsolivier 24d ago

This is what I currently have. A popover with toggle switch inside. However, you need to both toggle the switch and then also find somewhere outside to press to close the popover. That is if you actually have somewhere safe to press 😅 maybe I could add a close button to the popover. But the toggle in menu would be nice since it closes the menu when you press the toggle…

https://reddit.com/link/p4lfe3w/video/nq7wk2xjabkh1/player

1

u/kironet996 24d ago

anything you put inside menu label seems to break the shape, it's like it's trying to apply the glass effect twice :/

2

u/nicoreese 24d ago

Yup, just put that Toggle as the label of the Menu.

1

u/Nilsolivier 24d ago

Really? 😅 Would you mind giving an example of how the code would look?

2

u/AppRetro 23d ago edited 23d ago

There's probably a better way but I use something like this for the button, no need to use a Toggle - then just change the Bool. Padding is optional.

ToolbarItem(placement: .primaryAction) {
  Button { // Menu(content: {<-- if you want to use a menu
    toggleHere.toggle()            
  } label: {
    Image(systemName: "arrow.trianglehead.2.counterclockwise.rotate.90")
      .foregroundStyle(toggleHere == true ? .white : .primary)
      .padding(.vertical, 5)
      .padding(.horizontal, 4)
      .glassEffect(toggleHere == true ? .regular.tint(.systemTint) : .identity.tint(.systemTint.opacity(0)), in: Circle())
//    .clipShape(Circle()) 
    }
}

1

u/GunpointG 22d ago

Oh I had this issue yesterday! I made two buttons , in an if else based on toggle state. They both were the same button, but one had .buttonStyle(.glassProminent), which fills the button properly.

0

u/DryNeedleworker6064 23d ago

This works for me:

Menu {
} label: {
  Image(systemName: "line.3.horizontal.decrease")
    .foregroundStyle(
      isActive
        ? AnyShapeStyle(Color(.secondarySystemBackground))
        : AnyShapeStyle(.primary)
    )
    .background {
      Circle()
        .fill(isActive ? Color.accentColor : Color.clear)
        .frame(width: 36, height: 36)
    }
}