Search code examples
listswiftuisearchbar.searchable

Show .searchable search bar only when pulling down


So I have an SwiftUI view, that displays data in a List. You can search and filter through the objects. So far so easy, but this searchbar (initializised with .searchable()) is always visible. Only when you scroll down the list it disappears. How can I hide the search bar on appear and only when you pull down slightly it appears. Like in the default apple apps eg. notes. Is this possible with .searchable modifier or do i need to create a custom search bar, if so how? Here an example code:

        ZStack{
            NavigationView {
                List {
                    if(filteredTodayItems.isEmpty == false){
                        Section(header: ListHeader(text: "Today")) {
                            ForEach(filteredTodayItems) { item in
                                objectCell(item: item, rememberSheet: $showRememberSheet, currentItem: $currentItem, showRememberSheet: $showRememberSheet, showDetailSheet: $showDetailSheet, showAddingChangeSheet: $showAddingChangeSheet)
                            }
                            }
                    }else if(tomorrowItems.isEmpty && laterItems.isEmpty){
                        Text("Click on the Plus to enter a secret!")
                    }
                }
                .searchable(text: $searchText, prompt: Text("Search"))
                .navigationTitle("Secrets")
            }
        }

The funny thing i discovered now, is, that when i add .searchable(text: $searchText, prompt: Text("Search")) to the Section() it kind of works.. The search field is only displayed when pulling down, but the content of the sections is totally "destroyed", means swipe actions multiplied etc. When i add the modifier to an empty section at the top everything works, besides an empty section is visible

For better understanding, here is the full body:

        ZStack{
            NavigationView {
                    List {
                        if(filteredTodayItems.isEmpty == false){
                            Section(header: ListHeader(text: "Today")) {
                                ForEach(filteredTodayItems) { item in
                                    objectCell(item: item, rememberSheet: $showRememberSheet, currentItem: $currentItem, showRememberSheet: $showRememberSheet, showDetailSheet: $showDetailSheet, showAddingChangeSheet: $showAddingChangeSheet, isToday: true)
                                }
                            }
                        }else if(tomorrowItems.isEmpty && laterItems.isEmpty){
                            Text("Click on the Plus to enter a secret!")
                        }
                        if(filteredTomorrowItems.isEmpty == false){
                            Section(header: ListHeader(text: "Tomorrow")) {
                                ForEach(filteredTomorrowItems) { item in
                                    objectCell(item: item, rememberSheet: $showRememberSheet, currentItem: $currentItem, showRememberSheet: $showRememberSheet, showDetailSheet: $showDetailSheet, showAddingChangeSheet: $showAddingChangeSheet, isToday: false)
                                }
                            }
                        }
                        if(filteredLaterItems.isEmpty == false){
                            Section(header: ListHeader(text: "Later")) {
                                ForEach(filteredLaterItems) { item in
                                    objectCell(item: item, rememberSheet: $showRememberSheet, currentItem: $currentItem, showRememberSheet: $showRememberSheet, showDetailSheet: $showDetailSheet, showAddingChangeSheet: $showAddingChangeSheet, isToday: false)
                                }
                            }
                        }
                    }
                    .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .automatic))
                    .partialSheet(isPresented: $showRememberSheet) {
                        checkSecretView(currentItem: $currentItem, showRememberSheet: $showRememberSheet, showToast: $showToast, showToast2: $showToast2, value: $value)
                    }
                    .toolbar {
                        ToolbarItem (placement: .navigationBarLeading) {
                            Button(action: {
                                showSettings.toggle()
                            }) {
                                Image(systemName: "gear")
                            }
                        }
                        ToolbarItem (placement: .navigationBarTrailing) {
                            Button(action: {
                                showAddingSheet.toggle()
                            }) {
                                Image(systemName: "plus")
                            }
                        }
                    }
                    .listStyle(InsetGroupedListStyle())
                    .navigationTitle("Secrets")
            }
            .sheet(isPresented: $showAddingSheet) {
                AddingSheet(editingItem: nil)
            }
            .sheet(isPresented: $showDetailSheet) {
                InfoSheet(currentItem: $currentItem)
            }
            .sheet(isPresented: $showSettings) {
                Settings()
            }
            .sheet(isPresented: $showAddingChangeSheet) {
                let idString = UserDefaults.standard.string(forKey: "ToBeEditedLiveGoalID")
                let id = UUID(uuidString: idString ?? "")
                let objectToEdit = items.first(where: { $0.id == id})
                AddingSheet(editingItem: objectToEdit)
            }
            .attachPartialSheetToRoot()
            .simpleToast(isPresented: $showToast, options: toastOptions){
                HStack{
                    Image(systemName: "checkmark.circle.fill")
                    Text("Correctly Entered").bold()
                }
                .padding(.vertical,8)
                .padding(.horizontal,16)
                .background(.green.opacity(0.9))
                .foregroundColor(.white)
                .cornerRadius(10)
            }
            .simpleToast(isPresented: $showToast2, options: toastOptions){
                HStack{
                    Image(systemName: "xmark.circle.fill")
                    Text("Wrongly Entered").bold()
                }
                .padding(.vertical,8)
                .padding(.horizontal,16)
                .background(.red.opacity(0.9))
                .foregroundColor(.white)
                .cornerRadius(10)
            }
        }
        .blur(radius: isUnlocked ? 0 : 25)
        .disabled(!isUnlocked)
        .overlay(
            lockedScreen(color: Binding.constant(.accentColor) , isUnlocked: $isUnlocked)
                .opacity(isUnlocked ? 0 : 1)
        )
        .onAppear{
            isUnlocked = !bioSaveAuthActive
            if(!isUnlocked){
                authenticate()
            }
        }
    }

Solution

  • So, this is maybe not the ideal answer, because it does not solve my problem, but it sets my search bar equal to apples search bar in for example notes. Why is it default hidden in their app but not in mine? Simple! The moment the whole screen is filled with content / enough list entries are available, the search bar disappears, if not specifically pulled down. If their are not enough entries, it will always stay visible!