[英]swiftUI hiding textfield with firstResponder()
新人来了😬
我正在尝试使用不同的字体大小在 SwiftUI 中进行“输入”。
从我从其他帖子中了解到的情况,原生 TextField 无法做到这一点,因此我创建了一个带有 splicedText 的 HStack,并分别渲染我的文本的每个部分以达到预期的结果。 这一点工作正常。
但是,现在我有一个普通的 TextField 和我的“标签”,我不知道如何隐藏这个文本字段并仍然保持.decimalPad
打开。
这是我想要实现的外观:
这是我到目前为止:
正如你所看到的,我的价值出现了两次。 一种格式几乎正确,另一种未格式化(TextField)。
我尝试将.hidden()
添加到 TextField,虽然这确实隐藏了 TextField(),但我的 firstResponder() .decimalPad
不再显示,我无法输入我的值 :(
我不想只是将它设置为具有opacity(0)
,因为我不希望它在我看来占据任何空间。
此屏幕上最终将有 2 个输入,我需要能够单击“标签”以再次打开.decimalPad
。 然而,我还没有走到这一步。
这是呈现这个的代码:
import SwiftUI
import SwiftUIX
struct CreateEntryView : View {
class ViewModel: ObservableObject {
@Published var value = "$17.00" {
didSet {
let validCharSet = CharacterSet(charactersIn: "$1234567890.,")
print("value: " + value)
// add "$" prefix
if value.prefix(1) != "$" { value = "$" + value }
//check if the new string contains any invalid characters
if (value).rangeOfCharacter(from: validCharSet.inverted) != nil {
// remove any invalid characters
value = String(value.unicodeScalars.filter {
validCharSet.contains($0)
})
}
// replace ',' with '.' (required to handle all locales w/ decimalPad)
let test = value.replacingOccurrences(of: ",", with: ".")
print("replace comma: " + test)
// check if there's more than 2 decimals
// check if there's more than 1 dot
// check if there's more than 1 dollar-sign
}
}
}
@ObservedObject var viewModel = ViewModel()
// create splicedLabel for making label with varyign fontSize
var splicedLabel: [String] {
var spliceString = viewModel.value
// remove $ from string
spliceString.remove(at: spliceString.startIndex)
return spliceString.split(separator: ".").map(String.init)
}
var body: some View {
VStack {
HStack(alignment: .bottom, spacing: 0) {
Text("$")
.font(.body)
.fontWeight(.bold)
.padding(.bottom, 5)
if self.splicedLabel.indices.contains(0) {
Text(self.splicedLabel[0])
.font(.largeTitle)
.fontWeight(.bold)
}
if self.splicedLabel.indices.contains(1) {
HStack(alignment: .bottom, spacing: 0) {
Text(".")
.font(.body)
.fontWeight(.bold)
Text(self.splicedLabel[1])
.font(.body)
.fontWeight(.bold)
}.padding(.bottom, 5)
}
}
CocoaTextField("$123", text: $viewModel.value)
.isFirstResponder(true) // autoFocus
.keyboardType(.decimalPad)
}
}
}
非常感谢有关如何实现这一目标的一些意见。 也许我尝试在 HStack 中使用 Texts 来处理不同的 fontSize 是完全错误的。
也许你可以通过使用 UITextfield 和NSAttributedString来做到这一点,它们可以用不同的字体大小或颜色来装饰。
import UIKit
import SwiftUI
import Combine
struct MyTextField: UIViewRepresentable {
private var placeholder: String
@Binding private var text: String
private var textField = UITextField()
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(textField: self.textField, text: self._text)
}
func makeUIView(context: Context) -> UITextField {
textField.placeholder = self.placeholder
textField.font = UIFont.boldSystemFont(ofSize: 17)
textField.keyboardType = .decimalPad
textField.text = self.text
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
}
class Coordinator: NSObject {
private var dispose = Set<AnyCancellable>()
@Binding var text: String
init(textField: UITextField, text: Binding<String>) {
self._text = text
super.init()
let publisher = NotificationCenter.default
.publisher(for: UITextField.textDidChangeNotification, object: textField)
.compactMap { $0.object as? UITextField }
.share()
publisher.compactMap { $0.text }
.receive(on: RunLoop.main)
.assign(to: \.text, on: self)
.store(in: &dispose)
publisher.receive(on: RunLoop.main)
.sink(receiveValue: { (textField: UITextField) in
Coordinator.setAttributedString(textField: textField)
})
.store(in: &dispose)
}
static func setAttributedString(textField: UITextField) {
guard var text = textField.attributedText?.string else { return }
text = text.prefix(1) == "$" ? text : "$" + text
let dollarAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.black,
.font: UIFont.boldSystemFont(ofSize: 34)
]
let otherAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.black,
.font: UIFont.boldSystemFont(ofSize: 17)
]
let attributedText = NSMutableAttributedString(string: text)
attributedText.addAttributes(dollarAttributes, range: NSRange(location: 1, length: text.count - 1))
let strings = text.split(separator: ".")
if let dollar = strings.first, strings.count > 1 {
let range = NSRange(location: dollar.count, length: text.count - dollar.count)
attributedText.addAttributes(otherAttributes, range: range)
}
textField.attributedText = attributedText
}
}
}
extension MyTextField.Coordinator: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
}
}
struct ContentView: View {
@State var text: String = "$"
var body: some View {
VStack {
MyTextField("placeholder", text: self.$text).padding()
Text(self.text).foregroundColor(.red).padding()
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.