3

I am trying to make the search box in .searchable stick to the top without moving when there is no navigationBarTitle. Basically, when the box gets focused, there is an animation that moves the box upward and I would like to prevent that from hapenning. I just want the searchbox to stay stationary at the top, with just the cancel button coming from the right when the box is focused.

I tried all type of things such as .navigationBarHidden(true) but this totally removes the search bar as a whole.

Tried to add some spacer under in a vstack but it didnt push the bar up when unfocused, i tried to add some .ignoreSafeArea() but it didnt work. I tried to add a geometryReader and make the screen height larger than the display but it didnt move things up.

My codes:

struct SearchBarSM: View {
    
    @State var searchtxt:String = ""
    
    var body: some View {
        GeometryReader { geo in
            NavigationStack {
                ZStack {
                    VStack {
                        Text("Hello stackoverflow")
                    }
                }
                .navigationBarTitle("")
                .searchable(text: $searchtxt, prompt: "Search") {
                }
                .preferredColorScheme(.dark)
            }
        }
    }
}

When Unfocused:

enter image description here

When Focused:

enter image description here

The box moves up when focused.

1
  • You'll have to make your own search bar view Aug 4, 2023 at 0:16

2 Answers 2

2

As devdchaudhary said in the comments, I doubt this can be changed. You need to make your own search bar, and put it in the .principal position of the toolbar.

It's not that difficult to make your own search bar. Here, I have made something that behaves similar to the system's search bar. Adjust the colors and paddings as you see fit.

struct CustomSearchBar: View {
    @Binding var searchText: String
    
    @State var active = false
    
    var body: some View {
        HStack {
            HStack {
                Image(systemName: "magnifyingglass").foregroundColor(.gray)
                TextField("Search", text: $searchText, onEditingChanged: { editing in
                    withAnimation {
                        active = editing
                    }
                })
            }
            .padding(7)
            .background(Color(white: 0.9))
            .cornerRadius(10)
            .padding(.horizontal, active ? 0 : 50)
            
            Button("Cancel") {
                withAnimation {
                    active = false
                }
            }
            .opacity(active ? 1 : 0)
            .frame(width: active ? nil : 0)
        }
    }
}

Usage:

.toolbar {
    ToolbarItem(placement: .principal) {
        CustomSearchBar(searchText: $searchText)
    }
}
0

To achieve the behavior you described, you have to make a search bar view custom and then put it into the SearchBarSM view.

Example code:

SearchableCustom: View

struct SearchableCustom: View {
    
    @Binding var searchtxt: String
    @FocusState private var isSearchFocused: Bool // Track focus state
    
    var body: some View {
        HStack {
            HStack {
                Image(systemName: "magnifyingglass")
                TextField("Search", text: $searchtxt)
                    .focused($isSearchFocused) // Track focus state
                    .padding(.horizontal, 10)
                    .padding(.vertical, 8)
            }
            .padding(.horizontal)
            .background(Color(.secondarySystemBackground))
            .cornerRadius(10)
            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
            
            if isSearchFocused {
                Button("Cancel") {
                    searchtxt = ""
                    withAnimation(.spring()) {
                        isSearchFocused = false
                    }
                }
                .transition(.move(edge: .trailing)) // Add animation for cancel button
            }
        }
        .frame(maxWidth: .infinity)
        .padding(.horizontal)
    }
}

SearchBarSM: View

struct SearchBarSM: View {
    
    @State var searchtxt:String = ""
    
    var body: some View {
        VStack {
            SearchableCustom(searchtxt: $searchtxt)
            Text("Hello stackoverflow")
        }
        .frame(maxHeight: .infinity, alignment: .top)
        .preferredColorScheme(.dark)
    }
}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.