I've developed this component in SwiftUI:
let rows: [RowModel] = [RowModel(type: "single",
field: "single line field",
value: "Value 1"),
RowModel(type: "multiple",
field: "multiline field",
value: "This is a multiline field and shoul use 2 or more lines"),
RowModel(type: "single",
field: "single line field",
value: "Value 2")]
InfoBlock(rows: rows)
.padding([.leading, .trailing], 25)
.padding(.bottom, 8)
struct InfoBlock: View {
var rows: [RowModel]
init(rows: [RowModel]) {
self.rows = rows
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ForEach(0..<self.rows.count, id: \.self) {
let row = self.rows[$0]
let rowType = row.getType()
if rowType == "single" {
InfoSingleRow(row)
} else if rowType == "multiple" {
InfoMultipleRow(row)
}
if $0 < self.rows.count - 1 {
Rectangle()
.fill(Color("grey40"))
.frame(height: 2)
}
}
}
.background(Color.clear)
.overlay(RoundedRectangle(cornerRadius: 20)
.stroke(Color("grey40"), lineWidth: 1)
)
}
}
struct InfoSingleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
HStack(spacing: 0) {
Text(row.getField())
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Spacer()
Text(row.getValue())
.font(.uibook16)
.foregroundColor(Color("primary3_primary2"))
.lineLimit(1)
.multilineTextAlignment(.trailing)
}
.padding([.top, .bottom], 15)
.padding([.leading, .trailing], 13)
}
}
struct InfoMultipleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
HStack(spacing: 0) {
Text(row.getField())
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Spacer()
Text(row.getValue())
.font(.uibook16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.trailing)
}
.padding([.top, .bottom], 15)
.padding([.leading, .trailing], 13)
}
}
This produces the following output:
This is OK but I would like the fields to take 60% of the component width and the value the 40%. To do this I've tried to use GeometryReader:
struct InfoBlock: View {
var rows: [RowModel]
init(rows: [RowModel]) {
self.rows = rows
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ForEach(0..<self.rows.count, id: \.self) {
let row = self.rows[$0]
let rowType = row.getType()
if rowType == "single" {
InfoSingleRow(row)
} else if rowType == "multiple" {
InfoMultipleRow(row)
}
if $0 < self.rows.count - 1 {
Rectangle()
.fill(Color("grey40"))
.frame(height: 2)
}
}
}
.background(Color.clear)
.overlay(RoundedRectangle(cornerRadius: 20)
.stroke(Color("grey40"), lineWidth: 1)
)
}
}
struct InfoSingleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
let horizontalPadding: CGFloat = 13.0
GeometryReader { proxy in
HStack(spacing: 0) {
Text(row.getField())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.6, alignment: .leading)
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Text(row.getValue())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.4, alignment: .trailing)
.font(.uibook16)
.lineLimit(1)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.trailing)
}
.padding([.leading, .trailing], horizontalPadding)
.padding([.top, .bottom], 15)
}
}
}
struct InfoMultipleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
let horizontalPadding: CGFloat = 13.0
GeometryReader { proxy in
HStack(spacing: 0) {
Text(row.getField())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.6, alignment: .leading)
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Text(row.getValue())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.4, alignment: .trailing)
.font(.uibook16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.trailing)
}
.padding([.leading, .trailing], horizontalPadding)
.padding([.top, .bottom], 15)
}
}
}
But, as you can see, the output doesn't respect the height:
So I've tried to set the top/bottom paddings to the GeometryReader:
struct InfoBlock: View {
var rows: [RowModel]
init(rows: [RowModel]) {
self.rows = rows
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ForEach(0..<self.rows.count, id: \.self) {
let row = self.rows[$0]
let rowType = row.getType()
if rowType == "single" {
InfoSingleRow(row)
} else if rowType == "multiple" {
InfoMultipleRow(row)
}
if $0 < self.rows.count - 1 {
Rectangle()
.fill(Color("grey40"))
.frame(height: 2)
}
}
}
.background(Color.clear)
.overlay(RoundedRectangle(cornerRadius: 20)
.stroke(Color("grey40"), lineWidth: 1)
)
}
}
struct InfoSingleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
let horizontalPadding: CGFloat = 13.0
GeometryReader { proxy in
HStack(spacing: 0) {
Text(row.getField())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.6, alignment: .leading)
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Text(row.getValue())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.4, alignment: .trailing)
.font(.uibook16)
.lineLimit(1)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.trailing)
}
.padding([.leading, .trailing], horizontalPadding)
}
.padding([.top, .bottom], 15)
}
}
struct InfoMultipleRow: View {
private var row: RowModel
init(_ row: RowModel) {
self.row = row
}
var body: some View {
let horizontalPadding: CGFloat = 13.0
GeometryReader { proxy in
HStack(spacing: 0) {
Text(row.getField())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.6, alignment: .leading)
.font(.uilight16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.leading)
Text(row.getValue())
.frame(width: (proxy.size.width - 2 * horizontalPadding) * 0.4, alignment: .trailing)
.font(.uibook16)
.foregroundColor(Color("primary3_primary2"))
.multilineTextAlignment(.trailing)
}
.padding([.leading, .trailing], horizontalPadding)
}
.padding([.top, .bottom], 15)
}
}
The output is better:
But, as you can see, the multiline row only takes 1 line, it doesn't takes its full height.
What could I try?