如何在SwiftUI中创建带可编辑文本框的下拉菜单
SwiftUI 实现可编辑下拉菜单组件
以下是几种实用的实现方案,结合文本编辑与下拉选择的核心需求:
基础版(Sheet弹出选项)
通过TextField实现文本编辑,搭配Sheet弹出选项列表,适合需要轻量化弹出的场景:
import SwiftUI struct EditableDropdownView: View { @Binding var inputText: String let options: [String] @State private var showDropdown = false var body: some View { HStack { TextField("输入或选择选项", text: $inputText) .padding(.horizontal, 12) .padding(.vertical, 8) .border(Color.gray.opacity(0.3)) Button(action: { showDropdown.toggle() }) { Image(systemName: "chevron.down") .padding(.horizontal, 8) } } .sheet(isPresented: $showDropdown) { List(options, id: \.self) { option in Button(action: { inputText = option showDropdown = false }) { Text(option) } } .listStyle(.plain) .presentationDetents([.height(200)]) } } } // 使用示例 struct ContentView: View { @State private var selectedContent = "" var body: some View { VStack(spacing: 20) { EditableDropdownView(inputText: $selectedContent, options: ["北京", "上海", "广州", "深圳"]) .padding() Text("当前内容:\(selectedContent)") } } }
贴近原生下拉样式(输入框下方展开)
直接在输入框下方渲染选项列表,视觉上更贴近传统下拉菜单:
struct EditableDropdownView: View { @Binding var inputText: String let options: [String] @State private var showDropdown = false var body: some View { VStack(alignment: .leading, spacing: 0) { HStack { TextField("输入或选择选项", text: $inputText) .padding(.horizontal, 12) .padding(.vertical, 8) .border(Color.gray.opacity(0.3)) Button(action: { showDropdown.toggle() }) { Image(systemName: showDropdown ? "chevron.up" : "chevron.down") .padding(.horizontal, 8) } } if showDropdown { List(options, id: \.self) { option in Button(action: { inputText = option showDropdown = false }) { Text(option) .foregroundColor(inputText == option ? .blue : .primary) } } .listStyle(.plain) .frame(height: 200) .border(Color.gray.opacity(0.3)) } } .padding() } }
带搜索过滤的增强版
添加搜索功能,方便在大量选项中快速定位:
struct EditableDropdownView: View { @Binding var inputText: String let options: [String] @State private var showDropdown = false @State private var searchKeyword = "" private var filteredOptions: [String] { guard !searchKeyword.isEmpty else { return options } return options.filter { $0.localizedCaseInsensitiveContains(searchKeyword) } } var body: some View { VStack(alignment: .leading, spacing: 0) { HStack { TextField("输入或选择选项", text: $inputText) .padding(.horizontal, 12) .padding(.vertical, 8) .border(Color.gray.opacity(0.3)) Button(action: { showDropdown.toggle() if showDropdown { searchKeyword = "" } }) { Image(systemName: showDropdown ? "chevron.up" : "chevron.down") .padding(.horizontal, 8) } } if showDropdown { VStack(spacing: 0) { TextField("搜索选项", text: $searchKeyword) .padding(.horizontal, 12) .padding(.vertical, 8) .border(Color.gray.opacity(0.3)) List(filteredOptions, id: \.self) { option in Button(action: { inputText = option showDropdown = false }) { Text(option) .foregroundColor(inputText == option ? .blue : .primary) } } .listStyle(.plain) .frame(height: 200) } .border(Color.gray.opacity(0.3)) } } .padding() } }
以上方案均支持:
- 用户自由输入自定义文本
- 点击下拉按钮选择预设选项
- 数据双向绑定,父视图可同步获取输入内容
内容的提问来源于stack exchange,提问作者Darotudeen
相关产品推荐
相关产品推荐

