Last active
July 7, 2022 14:09
-
-
Save denis-obukhov/51d17e5c35a81590e9b49d2dac312e39 to your computer and use it in GitHub Desktop.
Don't hesitate to use .aspectRatio instead of GeometryReader in calculations based on relative container size. Especially when your subview has a dynamic content size effecting parent size back. Here's an example comparing two these approaches making a bar chart
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
struct GeometryReaderApproach: View { | |
private let values: [Double] = [152, 355, 475, 78, 173, 295] | |
private let maxValue: Double | |
init() { maxValue = values.max() ?? 0 } | |
var body: some View { | |
VStack { | |
let data = Array(zip(values.indices, values)) | |
// Why not use .enumerated? Well, in general it's is not necessarily the index of the paired value. | |
ForEach(data, id: \.0) { (index, value) in | |
HStack { | |
Text("\(index): ") | |
GeometryReader { geometry in | |
ZStack(alignment: .leading) { | |
RoundedRectangle(cornerRadius: 6) | |
.fill(Color.gray) | |
RoundedRectangle(cornerRadius: 6) | |
.fill(Color.green) | |
.frame(width: value / maxValue * geometry.size.width) | |
} | |
} | |
.frame(height: 15) | |
} | |
} | |
} | |
.padding() | |
} | |
} | |
struct AspectRatioApproach: View { | |
private let values: [Double] = [152, 355, 475, 78, 173, 295] | |
private let maxValue: Double | |
init() { maxValue = values.max() ?? 0 } | |
var body: some View { | |
VStack { | |
let data = Array(zip(values.indices, values)) | |
ForEach(data, id: \.0) { (index, value) in | |
HStack { | |
let baseRatio: Double = 20 / 1 | |
Text("\(index): ") | |
ZStack(alignment: .leading) { | |
RoundedRectangle(cornerRadius: 6) | |
.fill(Color.gray) | |
.aspectRatio(baseRatio, contentMode: .fit) | |
.frame(maxWidth: .infinity) | |
RoundedRectangle(cornerRadius: 6) | |
.fill(Color.red) | |
.aspectRatio(value / maxValue * baseRatio, contentMode: .fit) | |
.aspectRatio(baseRatio, contentMode: .fit) | |
} | |
.fixedSize(horizontal: false, vertical: true) | |
// Fix size to prevent bar from resizing | |
} | |
} | |
Text("Hello") | |
} | |
.padding() | |
} | |
} |
Author
denis-obukhov
commented
Jul 7, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment