6

I want to achieve a Search Bar with the new .searchable modifier, with .navigationBarDrawer(displayMode: .always). But if I start the App, the default position of the Search Bar is already "scrolled".

When I open the App

But this is what I want to achieve at the startup of the App:

What I want to achieve

This is my code:

struct SearchView: View {
    @State var searchText = ""
    var body: some View {
        NavigationView {
            List {
                Text("Search Bar")
            }
            .navigationBarTitle("Search")
            .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
        }
    }
}
aheze
  • 24,434
  • 8
  • 68
  • 125
X Æ A-12
  • 81
  • 1
  • 6

3 Answers3

1

I came across here as I had the same problem.

For me it worked (also iOS 15.7) when changing the order (or maybe the VStack around the list ‍♂️).

My code looks like the following:

// somewhere where the SearchView is used:
NavigationView {
    SearchView()
}

struct SearchView: View {
    @State var searchText = ""
    var body: some View {
        VStack {
            List {
                Text("Search Bar")
            }
        }
        .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
        .navigationBarTitleDisplayMode(.large)
        .navigationBarTitle("Search")
    }
}
theguy
  • 1,232
  • 1
  • 9
  • 21
0

Hacky Solution but it worked:

struct ContentView: View {
@State var searchText = ""
var body: some View {
    NavigationView {
        ZStack {
            Rectangle()
                .fill(Color.white)
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 1)
            
            List {
                Text("Search Bar")
            }
        }
        .searchable(text: $searchText, placement:.navigationBarDrawer(displayMode: .always))
        
        .navigationBarTitle("Search", displayMode: .large)
    }
}

}

RTXGamer
  • 3,215
  • 6
  • 20
  • 29
  • 1
    Thank you for your answer! Unfortunately, the Navigation Bar Title doesn't change to inline when scrolling anymore. – X Æ A-12 Jun 30 '21 at 08:06
  • @XÆA-12 you can check now I've updated the answer. Initially, I thought you want a large title all the time. – RTXGamer Jun 30 '21 at 08:44
  • 1
    Nice, works perfectly. Although it is a bit hacky :) Do you know if this is on purpose from apple or just a bug? – X Æ A-12 Jun 30 '21 at 19:14
  • It only happens when you add searchable(text: to it. So it purposefully there for a reason, but don't know what it is. :) – RTXGamer Jul 01 '21 at 05:11
0

If you're okay with using dependencies, here's a solution using SwiftUI-Introspect

struct SearchView: View {
    @State var searchText = ""
    let names: [String] = ["Joe", "Dylan", "Jim", "Andy"]

    var body: some View {
        NavigationView {
            List {
                ForEach(names, id: \.self) { name in
                    Text(name)
                }
            }
            .navigationBarTitle("Search")
            .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
            .introspectNavigationController { navigationController in
                navigationController.navigationBar.sizeToFit()
            }
        }
    }
}

Basically, I found the original UIKit answer from here and found that asking the navigationController to call sizeToFit() fixed the issue (in my testing). From the documentation, sizeToFit tells the navigation bar to resize itself to its own needs which is to have a large title.

I believe this was a SwiftUI bug in iOS 15 which is now fixed in iOS 16+ since this behavior no longer happens when using .navigationBarDrawer(displayMode: .always) with searchable.

code24
  • 458
  • 1
  • 3
  • 14