SwiftUI TextField实现不可选中后缀及值为0时隐藏的方案
实现带不可选中后缀的数值TextField(值为0时显示占位符)
需要实现一个TextField,满足以下需求:
- 显示不可选中、不可编辑的后缀(如单位)
- 当值为0时,隐藏数值并显示占位符
- 解决原方案中NumberFormatter在decimalPad下无法实时更新、后缀可被删除的问题
核心思路是通过组合TextField和独立Text视图实现不可编辑的后缀,同时手动处理输入过滤、数值转换和显示逻辑,替代NumberFormatter的实时格式化限制:
完整实现代码
struct SuffixTextFieldView: View { @State private var inputText = "" @State private var value = 0.0 private let suffix = "SUFFIX" private let placeholder = "Cost" var body: some View { HStack(spacing: 0) { TextField("", text: $inputText) .placeholder(when: inputText.isEmpty && value == 0.0) { Text(placeholder) .foregroundColor(.secondary) } .keyboardType(.decimalPad) .onChange(of: inputText) { newValue in // 过滤输入,只保留数字和单个小数点 let filtered = newValue.filter { "0123456789.".contains($0) } if filtered != newValue { inputText = filtered } // 转换为数值,处理空输入的情况 if let number = Double(filtered) { value = number } else if filtered.isEmpty { value = 0.0 } } .onEditingChanged { isEditing in if !isEditing { // 失去焦点时格式化显示:值为0则清空输入框(显示占位符) if value == 0.0 { inputText = "" } else { inputText = String(format: "%.2f", value) } } else { // 开始编辑时,若当前值为0则清空输入框 if value == 0.0 { inputText = "" } } } // 仅当值不为0时显示后缀,后缀为不可编辑的独立视图 if value != 0.0 { Text(suffix) .foregroundColor(.secondary) .padding(.trailing, 8) } } .padding(.horizontal, 16) .padding(.vertical, 12) .background(Color(.systemGray6)) .cornerRadius(8) .onAppear { // 初始值处理:非0值则格式化显示 if value != 0.0 { inputText = String(format: "%.2f", value) } } } } // 自定义占位符扩展,实现值为0时显示占位符 extension View { func placeholder<Content: View>( when shouldShow: Bool, alignment: Alignment = .leading, @ViewBuilder placeholder: () -> Content ) -> some View { ZStack(alignment: alignment) { placeholder().opacity(shouldShow ? 1 : 0) self } } } #Preview { SuffixTextFieldView() }
关键逻辑说明
- 不可编辑后缀:通过HStack将TextField和独立的Text视图组合,后缀不属于TextField内容,因此无法被选中或删除,仅在值不为0时显示。
- 输入过滤:在
onChange中过滤输入内容,只允许数字和单个小数点,确保输入合法性。 - 占位符控制:通过自定义
placeholder扩展,在输入框为空且值为0时显示占位符。 - 编辑状态处理:
- 开始编辑时,若当前值为0则清空输入框,方便用户输入新数值。
- 失去焦点时,自动格式化数值(保留两位小数),值为0则清空输入框显示占位符。
- 实时数值同步:输入过程中实时将输入文本转换为数值,确保
value状态与输入内容一致。
内容的提问来源于stack exchange,提问作者Elektronenhirn
相关产品推荐
相关产品推荐

