Skip to content

Instantly share code, notes, and snippets.

@op183
Last active March 10, 2020 22:41
Show Gist options
  • Save op183/24607b6309f7d1ea8f3aaf02d17e4ed3 to your computer and use it in GitHub Desktop.
Save op183/24607b6309f7d1ea8f3aaf02d17e4ed3 to your computer and use it in GitHub Desktop.
example of custom binding
//
// ContentView.swift
// tmp073
//
// Created by Ivo Vacek on 03/03/2020.
// Copyright © 2020 Ivo Vacek. All rights reserved.
//
import SwiftUI
struct UnitPicker: View {
let label: String
let data: [String]
@Binding var selection: Int
var body: some View {
Picker(label, selection: $selection) {
ForEach(0 ..< data.count) { (idx) in
Text(self.data[idx])
}
}.pickerStyle(WheelPickerStyle())
}
}
struct MyTextFieldStyle: TextFieldStyle {
@Binding var focused: Bool
func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding(10)
.background(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.stroke(focused ? Color.secondary : Color.clear, lineWidth: 3)
).padding()
}
}
struct ContentView: View {
let units = [UnitTemperature.celsius, UnitTemperature.fahrenheit, UnitTemperature.kelvin]
@State var value = Measurement(value: 0.0, unit: UnitTemperature.celsius)
@State var toUnit = 0
@State var empty = true
var result: String {
format(value: value.converted(to: units[toUnit]).value)
}
var body: some View {
let unitBinding = Binding<Int>(get: {
self.units.firstIndex(of: self.value.unit) ?? 0
}) { (idx) in
let v = self.value.value
self.value = Measurement(value: v, unit: self.units[idx])
}
let binding = Binding<String>(get: {
if self.empty { return "" } else {
return self.format(value: self.value.value)
}
}) { (str) in
self.empty = str.isEmpty
// before string to double
// replace decimal separator to "." !!!
let dot = Locale.current.decimalSeparator ?? "."
let s = str.replacingOccurrences(of: dot, with: ".")
self.value.value = Double(s) ?? 0.0
}
return Form {
Section(header: Text("Temperature").font(.title)) {
HStack {
TextField("0", text: binding)
.font(.title)
.textFieldStyle(MyTextFieldStyle(focused: .constant(true)))
.keyboardType(.numbersAndPunctuation)
Spacer(minLength: 20)
UnitPicker(label: "", data: units.map {$0.symbol }, selection: unitBinding)
.frame(width: 50, height: 100).clipped()
}
HStack {
TextField("0", text: .constant(result))
.font(.title)
.disabled(true)
.textFieldStyle(MyTextFieldStyle(focused: .constant(false)))
Spacer(minLength: 20)
UnitPicker(label: "", data: units.map {$0.symbol }, selection: $toUnit)
.frame(width: 50, height: 100).clipped()
}
}
}.padding()
}
func format(value: Double) -> String {
// for presentation
// replace "." with decimal separator
let dot = Locale.current.decimalSeparator ?? "."
var s = String(format: "%f", value)
.replacingOccurrences(of: ".", with: dot)
.reversed()
.drop(while: {$0 == "0"})
.reversed()
.map(String.init)
.joined()
if let last = s.last, String(last) == dot {
s.removeLast()
}
return s
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment