Swiftui数字Textfield最大值和最小值

发布于 2025-02-07 16:57:48 字数 443 浏览 1 评论 0原文

我正在尝试实现一些接受所需范围内任何数字的文本场。例如,如果用户输入一个值,我希望它能动态地从min到最大。但是,我不知道如何在文本场中控制它。

struct Container {
var textInput: Double
}

struct ContentView: View {
@State private var container = Container
var body: some View {
TextField("", value: $container.textInput, format: .number)
                        .keyboardType(.decimalPad)
                        .frame(width: 200, height: 20)
                        .padding()
}
}

I'm trying to implement some TextFields that accept any number in a desired range. This is, if the user is entering an value, I'd like it to be from min to max dynamically , for example. However, I don't know how to control this in a TextField.

struct Container {
var textInput: Double
}

struct ContentView: View {
@State private var container = Container
var body: some View {
TextField("", value: $container.textInput, format: .number)
                        .keyboardType(.decimalPad)
                        .frame(width: 200, height: 20)
                        .padding()
}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

霞映澄塘 2025-02-14 16:57:48

遇到了完全相同的问题,并提出了这一点:
使用自定义格式 - 它不是完美的,但它可以按照我想要的方式工作。

class BoundFormatter: Formatter {
    
    var max: Int = 0
    var min: Int = 0
    
    func clamp(with value: Int, min: Int, max: Int) -> Int{
        guard value <= max else {
            return max
        }
        
        guard value >= min else {
            return min
        }
        
        return value
    }

    func setMax(_ max: Int) {
        self.max = max
    }
    func setMin(_ min: Int) {
        self.min = min
    }
    
    override func string(for obj: Any?) -> String? {
        guard let number = obj as? Int else {
            return nil
        }
        return String(number)
        
    }

    override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {

        guard let number = Int(string) else {
            return false
        }
        
        obj?.pointee = clamp(with: number, min: self.min, max: self.max) as AnyObject
        
        return true
    }
    
}

然后,我这样使用它:

let max: Int = 100
let min: Int = 0
var formatter: BoundFormatter {
   let formatter = BoundFormatter()
   formatter.setMax(self.max)
   formatter.setMin(self.min)
   return formatter
}

@Binding var value: Int = 0

//// VIEW BODY \\\\

TextField("Number here:", value: $value, formatter: boundFormatter)

您甚至可以通过将Max Max设置为格式化器作为绑定来改进此版本,以便您具有动态界限。

class BoundFormatter: Formatter {
    
    @Binding var max: Int
    @Binding var min: Int

    // you have to add initializers
    init(min: Binding<Int>, max: Binding<Int>) {
       self._min = min
       self._max = max

       super.init()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented"
    }
    ...
}


/// usage

TextField("Number here:", value: $value, formatter: BoundFormatter(min: .constant(0), max: $max))

Had the exact same problem and came up with this:
Using a custom formatter – it’s not perfect but it works the way I want it to.

class BoundFormatter: Formatter {
    
    var max: Int = 0
    var min: Int = 0
    
    func clamp(with value: Int, min: Int, max: Int) -> Int{
        guard value <= max else {
            return max
        }
        
        guard value >= min else {
            return min
        }
        
        return value
    }

    func setMax(_ max: Int) {
        self.max = max
    }
    func setMin(_ min: Int) {
        self.min = min
    }
    
    override func string(for obj: Any?) -> String? {
        guard let number = obj as? Int else {
            return nil
        }
        return String(number)
        
    }

    override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {

        guard let number = Int(string) else {
            return false
        }
        
        obj?.pointee = clamp(with: number, min: self.min, max: self.max) as AnyObject
        
        return true
    }
    
}

Then I use it like this:

let max: Int = 100
let min: Int = 0
var formatter: BoundFormatter {
   let formatter = BoundFormatter()
   formatter.setMax(self.max)
   formatter.setMin(self.min)
   return formatter
}

@Binding var value: Int = 0

//// VIEW BODY \\\\

TextField("Number here:", value: $value, formatter: boundFormatter)

You can even improve this version by setting min max in the formatter as bindings, so you have dynamic bounds.

class BoundFormatter: Formatter {
    
    @Binding var max: Int
    @Binding var min: Int

    // you have to add initializers
    init(min: Binding<Int>, max: Binding<Int>) {
       self._min = min
       self._max = max

       super.init()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented"
    }
    ...
}


/// usage

TextField("Number here:", value: $value, formatter: BoundFormatter(min: .constant(0), max: $max))
野心澎湃 2025-02-14 16:57:48
 TextField(
        .onChange(of: text, perform: {
          text = String($0.prefix(1))
        })
 TextField(
        .onChange(of: text, perform: {
          text = String($0.prefix(1))
        })
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文