You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:55:17