I'm building an iOS app and currently I've found a strange behaviour with Divider component.
See the following screenshot:
The chevron on the top right side makes the other two(or more) components appear/disappear, the problem happens with the vertical Divider which should appear next to CONTROLS A.
The general SwiftUI hierarchy for the view is something similar to ScrollView -> VStack -> ForEach -> [HStack -> Img Divider VStack (with SOME TEXT + CONTROLS X)].
Note that it happens not only for the first component. Controls X contains SwiftUI components, nothing custom.
Now some interesting facts I've found after debugging:
- If I make the Divider show/disappear with a boolean flag which changes on tap, the Divider is shown as expected
- If I make the Divider show/disappear with a boolean flag which changes on "onAppear" the Divider is not shown
- The Divider view is included with width 0.33 but height 0 (that's the real problem)
- Adding or removing views to "Controls A" can make the Divider show
Been trying to find the cause for it without success so I'm inclined to think it's probably a bug where the final height is not properly updated for the Divider component.
Update: The issue happens only on some devices, iPhone 12 is one of them.
Here's some code to reproduce a similar issue (in this case the divider is visible but its height is wrong):
struct BugScreen: View {
var body: some View {
VStack {
Text("Bug Test")
ScrollView(showsIndicators: false) {
ForEach((1..<3)) { i in
MyView(index:i)
}
Spacer(minLength: 75)
}
.padding(.horizontal, 20)
}
.navigationBarTitle("", displayMode: .inline)
}
}
struct MyView: View {
@State var expanded = false
var index: Int
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 15) {
Image("ImageName")
.resizable()
.frame(width: 50, height: 50)
Divider()
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: 5) {
HStack {
Text("Test \(index)")
.font(.headline)
.fontWeight(.light)
.fixedSize(horizontal: false, vertical: true)
Spacer()
Image(systemName: expanded ? "chevron.up": "chevron.down")
.padding(.leading, 10)
.font(Font.body.weight(.thin))
}
}
Divider()
Text("Some text")
.fixedSize(horizontal: false, vertical: true)
}
}
.padding([.vertical, .leading])
.padding(.trailing, 5)
.background(
RoundedRectangle(cornerRadius: expanded ? 0: 25, style: .continuous).foregroundColor(.white)
)
.onTapGesture {
withAnimation { expanded.toggle() }
}
if expanded {
Divider().background(Color(.black))
VStack {
ForEach((1..<4)) { control in
Spacer(minLength: 10)
MyControlsView()
Divider().background(Color(.black))
}
Text("More text")
}
.padding(.horizontal, 10)
.background(Color.white)
}
Divider().background(Color(.black))
}
}
struct MyControlsView: View {
@State var sliderValue = 0.0
var body: some View {
VStack {
HStack {
Image("image_name")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
Divider()
VStack(alignment: .leading) {
Text("My controls")
Divider()
VStack(alignment: .leading) {
Slider(value: $sliderValue, in: 0...100)
Slider(value: $sliderValue, in: 0...100)
Slider(value: $sliderValue, in: 0...100)
Text("Hello")
Text("Some other text")
}
.disabled(false)
.padding(0)
.background(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.foregroundColor(
.clear
)
)
}
}
}
.accentColor(.black)
.padding()
}
}