In my SwiftUI application, I'm trying to implement a UI similar to this:
I've added the two rows for category 1 and category 2. The result looks like this:
NavigationView {
VStack(alignment: .leading) {
CategoryRow(...)
CategoryRow(...)
Spacer()
}
.navigationBarTitle(Text("Featured"))
}
Now, when added the view for the third category – an VStack
with images – the following happens:
This happened, after I replaced Spacer()
, with said VStack
:
VStack(alignment: .leading) {
Text("Rivers")
.font(.headline)
ForEach(self.categories["Rivers"]!.identified(by: \.self)) { landmark in
landmark.image(forSize: 200)
}
}
My CategoryRow
is implemented as follows:
VStack(alignment: .leading) {
Text(title)
.font(.headline)
ScrollView {
HStack {
ForEach(landmarks) { landmark in
CategoryItem(landmark: landmark, isRounded: self.isRounded)
}
}
}
}
Question
It seems that the views are compressed. I was not able to find any compression resistance or content hugging priority modifiers to fix this.
I also tried to use .fixedSize()
and .frame(width:height:)
on CategoryRow
.
How can I prevent the compression of these views?
Update
I've tried embedding the whole outer stack view in a scroll view:
NavigationView {
ScrollView { // also tried List
VStack(alignment: .leading) {
CategoryRow(...)
CategoryRow(...)
ForEach(...) { landmark in
landmark.image(forSize: 200)
}
}
.navigationBarTitle(Text("Featured"))
}
}
...and the result is worse:
It looks like is not enough space for all your views in
VStack
, and it compresses some of them. You can embed it into theScrollView
I think your topmost view (in the NavigationView) needs to be a List, so that it is scrollable:
Or use a ScrollView.
A stack automatically fits within a screen. If you want your content to exceed this, you would have used a ScrollView or a TableView etc i UIKit
EDIT:
Actually, a little Googling brought this result, which seems to be exactly what you are making: https://developer.apple.com/tutorials/swiftui/composing-complex-interfaces
You could try to add a
layoutPriority()
operator to your firstVStack
. This is what the documentation says about the method:So it's a bit like the content compression resistance priority in Autolayout. But the default value here is 0, so you just have to set it to 1 to get the desired effect, like this:
Hope it works!
You might prevent the views in VStack from being compressed by using
For example: I have the following VStack:
Which render compressed Text()
VStack with compressed elements
When I add .fixedSize(horizontal: false, vertical: true) it doesn't compress anymore
VStack doesn't compresss content