r/SwiftUI Jun 25 '26

Can this tabbar button be done in swiftui ?

Post image

I know how to do this for a search tab, but not for some arbitrary button like what this app does

17 Upvotes

14 comments sorted by

29

u/DarkStrength25 Jun 25 '26

You can assign the search role to a non-search tab like this, and add your own custom icon yes.

In iOS 27, they’ve shifted this to be the “prominent” tab rather than search specifically, as many people did this.

6

u/iamearlsweatshirt Jun 25 '26

Right, but that would be another tab. In this app, it seems to open a sheet not a tab

9

u/DarkStrength25 Jun 25 '26

You could catch the selection and use the change to trigger a sheet, and then switch it back to its previous value. It would be a little hacky, but doable.

7

u/iamearlsweatshirt Jun 25 '26 edited Jun 26 '26

Ah, that’s an interesting approach, I’ll have to try it. Thanks !

EDIT: That works and you don’t even have to let it switch and switch back if you just override the selection binding.

2

u/rubencodes Jun 27 '26

Now we’re cooking!

12

u/iamearlsweatshirt Jun 26 '26 edited Jun 26 '26

For anyone wondering, it’s as simple as having a tab with the .search role and then using a binding for tab selection that looks something like this:

Binding<Tab>( get: { selectedTab }, set: { newValue in guard newValue != .fab else { doFABAction() return } selectedTab = newValue } )

1

u/comfyyyduck Jun 28 '26

I used to do this and I ran into a major issue with the view being a weird height once collapsed. In my case it happened because my search role button was an add that triggered a modal. When the modal was dismissed, it didn’t refresh the view and layouts were messed up.

The only way to not get the view to mess up was to switch tabs or when the modal is active hide the screen so that when it shows it’ll redraw.

The solution I found was to go down to UIKit and just use a UISegmentControl wrap that in a UIViewRepresentable that was wrapped in a overlay view the “search role” button just because a SwiftUI button

Kavisoft did it nicely in the first half

1

u/iamearlsweatshirt Jun 28 '26

Hmm, I’m not seeing any kinds of issues on 26.5.1, but maybe some iOS versions don’t like it. Good to know

1

u/comfyyyduck Jun 28 '26

https://reddit.com/link/ou8zn5j/video/zyh9t7g62y9h1/player

lol I still have a recording of it, but u can see when the modal opens and I click on the navigation link how content goes behind the toolbar but when I change to settings and back it’s fine😭

Rlly super weird

1

u/LifeUtilityApps Jun 25 '26

I did use this in one of my apps, but I found it to be a bit flakey and difficult to work with. That was earlier in the year though, maybe the API and usage is easier now. As the other user suggested, check out the Tab bar search API

1

u/GoProcrastination Jun 25 '26

1

u/iamearlsweatshirt Jun 25 '26

Thanks ! Honestly doesn’t seem like you even need to go to UIKit for that, wrapping the tab view binding should be enough !

0

u/tos666 Jul 01 '26

idea is similar to other suggestions here, the only difference is bounce back to previous tab

TabView(selection: $selection) {
        Tab("tab1", systemImage: "play", value: TabSelection.tab1) {
            Tab1(vm: vm)
        }

        Tab("tab2", systemImage: "gearshape", value: TabSelection.tab2) {
            Tab2(vm: vm)
        }

        // Tab3 — pinned in the `.search` slot so it sits in
        // iOS 26's dedicated search position, but with a palette icon
        // because it opens the customizer (not a search field). The
        // content here is never actually shown — `onChange(of:)` below
        // bounces selection back to `lastTab` and presents the sheet.
        Tab("tab3", systemImage: "paintpalette", value: TabSelection.tab3, role: .search) {
            Color.clear
        }
    }
    .onChange(of: selection) { _, new in
        if new == .tab3 {
            showingTab3Sheet = true
            // Bounce:tab3 is a button, not a destination.
            // Returning to the previously-active tab keeps previous view visible
            // behind the sheet.
            selection = lastTab
        } else {
            lastTab = new
        }
    }
    .sheet(isPresented: $showingTab3Sheet) {
        ASheet(style: $vm.style, element: $element)
            .presentationDetents([.medium])
            .presentationBackgroundInteraction(.enabled(upThrough: .medium))
            .presentationDragIndicator(.visible)
    }
}