Reputation: 868
I am making a UI to change the 3D coordinates of an object, and I thought it would make sense to put all three on the same line with a label beforehand, sort of like System Preferences does for number separators :
However, doing so messes up the alignment of the whole form, and I'm not sure how to resolve this (except by adding VStack
s and HStack
s everywhere, which I really hope is not the best available solution) :
Here is the code driving the view :
struct ObjectSettingsView: View {
@State var object : Object
var body : some View {
Form {
TextField("Name:", text: $object.name, prompt : Text("New Object"))
Toggle(
"Visible",
isOn: $object.visible
)
Divider()
HStack {
Text("Coordinates:")
NumberView(label : "X:", number : object.coordinates.x)
NumberView(label : "Y:", number : object.coordinates.y)
NumberView(label : "Z:", number : object.coordinates.z)
}
}
}
}
struct NumberView : View{
var label : String
@State var number : Int32
var body : some View {
HStack {
TextField(
self.label,
value: self.$number,
formatter: NumberFormatter()
)
Stepper("", value: self.$number, in: 1...8)
.labelsHidden()
}
}
}
( I know this really should be using a ViewModel
, I'm just trying to figure out how forms work right now )
Upvotes: 2
Views: 642
Reputation: 51
// static let left = GridItem.Size.flexible(minimum: 10, maximum: .infinity)
static let left = GridItem.Size.flexible(minimum: 40, maximum: 100)
static let right = GridItem.Size.flexible(minimum: 40, maximum: 200)
let columns = [
GridItem(left, alignment: .trailing),
GridItem(right, alignment: .leading),
]
The problem is that the size structs are set to .infinity I changed the column settings like above with fixed max values. To get all infos see Apple Docs about GridItem.
Upvotes: 0
Reputation: 51
I add @Binding and LazyVGrid to your Code.
Maybe this helps:
struct ObjectData {
var name: String = "New Object"
var visible: Bool = true
var coordinates_x: Int32 = 0
var coordinates_y: Int32 = 0
var coordinates_z: Int32 = 0
}
struct ContentView: View {
@State var data = ObjectData()
let columns = [
GridItem(alignment: .trailing),
GridItem(alignment: .leading),
]
var form: some View {
LazyVGrid(columns: columns) {
Text("Name:")
TextField("", text: $data.name)
Text("blind").opacity(0)
Toggle("Visible:", isOn: $data.visible)
Text("Coordinates:")
HStack {
NumberView(label : "X:", number : $data.coordinates_x)
NumberView(label : "Y:", number : $data.coordinates_y)
NumberView(label : "Z:", number : $data.coordinates_z)
}
}
}
var body : some View {
VStack() {
form
Text(" --- Check --- ")
Text(String(describing: data))
}
.frame(width: 400.0)
}
}
struct NumberView : View{
var label : String
@Binding var number : Int32
var body : some View {
HStack {
TextField(
self.label,
value: self.$number,
formatter: NumberFormatter()
)
Stepper("", value: self.$number, in: 1...8)
.labelsHidden()
}
}
}
Upvotes: 1
Reputation: 868
Separating things into two Form
s almost does the trick, although labels are still not exactly aligned as in system Preferences :
struct ObjectSettingsView: View {
@State var object : Object
var body : some View {
VStack {
Form {
TextField("Name:", text: $object.name, prompt : Text("New Object"))
Toggle("Visible", isOn: $object.visible)
}
Divider()
Form {
HStack {
Text("Coordinates:")
NumberView(label : "X:", number : object.coordinates.x)
NumberView(label : "Y:", number : object.coordinates.y)
NumberView(label : "Z:", number : object.coordinates.z)
}
}
}
.padding()
}
}
Upvotes: 0