Last active
December 29, 2022 22:27
-
-
Save mattyoung/4dacf36fa209c4d808e1f27d379c1a41 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
//import Combine | |
struct NumbersOnlyViewModifier: ViewModifier { | |
@Binding var text: String | |
var includeDecimal: Bool | |
func body(content: Content) -> some View { | |
content | |
.keyboardType(includeDecimal ? .decimalPad : .numberPad) | |
.onChange(of: text) { newValue in | |
if includeDecimal { | |
do { | |
let fixup: String | |
if let lastChar = newValue.last, !lastChar.isNumber { // we have a decimal point at the end? | |
fixup = String(lastChar) | |
} else { | |
fixup = "" | |
} | |
let parsedResult = try Double(newValue, format: .number).formatted(.number.grouping(.never)) + fixup | |
if newValue != parsedResult { | |
text = String(newValue.dropLast()) | |
} | |
} catch { | |
text = String(newValue.dropLast()) | |
} | |
} else { | |
do { | |
let sanitizedNewValue = String(newValue.dropFirst(newValue.prefix(while: { $0 == "0" }).count)) | |
let parsedResult = try Int(sanitizedNewValue, format: .number).formatted(.number.grouping(.never)) | |
if sanitizedNewValue != parsedResult { | |
text = String(newValue.dropLast()) | |
} else if newValue != sanitizedNewValue { | |
text = sanitizedNewValue | |
} | |
} catch { | |
text = String(newValue.dropLast()) | |
} | |
} | |
} | |
} | |
} | |
extension View { | |
func numberOnly(_ text: Binding<String>, includeDecimal: Bool = false) -> some View { | |
modifier(NumbersOnlyViewModifier(text: text, includeDecimal: includeDecimal)) | |
} | |
} | |
struct NumericTextFieldDemo: View { | |
@State private var anInteger = 0 | |
@State private var aDecimal = 0.0 | |
@State private var textInt = "0" | |
@State private var textDec = "0." | |
var body: some View { | |
VStack { | |
// this allows for only Int values, but the problem is you can enter anything, not number only | |
// how to restrict this to number only? | |
// with a String value TextField, you can monitor the input and not allow non-number | |
// but here we have nothing to monitor. | |
TextField("Enter a integer", value: $anInteger, format: .number) | |
.textFieldStyle(.roundedBorder) | |
.keyboardType(.numberPad) | |
TextField("Enter a integer", value: $aDecimal, format: .number) | |
.textFieldStyle(.roundedBorder) | |
.keyboardType(.decimalPad) | |
TextField("Number only!", text: $textInt) | |
.numberOnly($textInt) | |
TextField("Number and decimal only!", text: $textDec) | |
.numberOnly($textDec, includeDecimal: true) | |
} | |
} | |
} | |
struct NumericTextFieldDemo_Previews: PreviewProvider { | |
static var previews: some View { | |
NumericTextFieldDemo() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment