[SUI] 搜索栏

发布: (2026年2月3日 GMT+8 06:02)
4 min read
原文: Dev.to

Source: Dev.to

(看起来您只提供了来源链接,没有提供需要翻译的正文内容。请提供要翻译的文本,我将为您翻译成简体中文。)

NavigationStack 可以通过 searchable 修饰符添加搜索栏。
它的签名如下:

searchable(
    text: Binding,
    tokens: Binding? = nil,
    suggestedTokens: [Token]? = nil,
    placement: SearchFieldPlacement = .automatic,
    prompt: String? = nil,
    token: () -> TokenView? = { nil }
)
  • text:用户输入的文本。
  • tokens:用于跟踪已显示的 token。
  • suggestedTokens:建议的 token 列表。
  • placement:搜索栏的位置(automaticnavigationBarDrawersidebartoolbar 等)。
  • prompt:占位符文字。
  • token:用于显示 token 的视图。

基本使用

struct Person: Identifiable {
    let id = UUID()
    let name: String
}

private let people: [Person] = [
    .init(name: "David Goyes"),
    .init(name: "Midoriya Izuku"),
    .init(name: "Tanjiro Kamado"),
    .init(name: "David Beckham"),
]

struct ContentView: View {
    @State private var searchText: String = ""

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(text: $searchText, prompt: "¿A quién busca?")
        }
    }
}

在 iOS 26 中,默认情况下,搜索栏位于底部(相当于 toolbar)。当它成为 first responder 时,会显示在键盘上方。

使用 onChange 更新列表

如果希望存储过滤后的结果,需要手动更新它:

struct ContentView: View {
    @State private var searchText: String = ""
    @State private var filteredPeople: [Person] = []

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(text: $searchText, prompt: "¿A quién busca?")
            .onChange(of: searchText, initial: true) {
                filterPeople()
            }
        }
    }

    private func filterPeople() {
        filteredPeople = searchText.isEmpty
            ? people
            : people.filter { $0.name.localizedStandardContains(searchText) }
    }
}

搜索栏的位置

  • automatic / toolbar:始终显示在底部工具栏。
  • navigationBarDrawer:向上滚动列表时隐藏,向下滚动时重新出现。

要在导航栏中始终显示它:

struct ContentView: View {
    @State private var searchText: String = ""

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .always),
                prompt: "¿A quién busca?"
            )
        }
    }
}

使用 searchFocused 进行编程式聚焦

可以通过 searchFocused(_:)@FocusState 来控制搜索栏的焦点:

struct ContentView: View {
    @State private var searchText: String = ""
    @FocusState private var isFocused: Bool   // <-- 栏目的焦点

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Buscar", systemImage: "magnifyingglass") {
                        isFocused = true               // 聚焦搜索栏
                    }
                }
            }
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .automatic),
                prompt: "¿A quién busca?"
            )
            .searchFocused($isFocused)               // 控制焦点
        }
    }
}

toolbar 中的 “Buscar” 按钮将 isFocused 设置为 true,这会显示键盘并将光标放在搜索栏中。

Back to Blog

相关文章

阅读更多 »

[SUI] LabeledContent

LabeledContent(https://developer.apple.com/documentation/swiftui/labeledcontent)是一个将标签附加到控件的容器。基本用法示例:swift struct C…

[SUI] 表单 (Form)

Form Form 是一个用于分组控件的容器,主要用于某些功能的配置。它在 List 中呈现控件,并且…

[SUI] 多日期选择器

使用 MultiDatePicker。MultiDatePicker 允许在 SwiftUI 中选择多个日期。Swift 初始化器 MultiDatePicker.init_:selection:in: - titleKey: 标题键。