I am working on a dynamic indicator for a tabView to show a slideshow of images (say 5 images). I am using GeometryReader to determine the minX position of the first picture. This works fine until I scroll to the third picture, where the minX is no longer read.
Here is the code:
struct topTabView: View {
private var numberOfImages = ["0", "1", "2", "3", "4"]
@State private var currentIndex = 0
@State var offset: CGFloat = 0
var body: some View {
ScrollView(.init()){
TabView(selection: $currentIndex) {
ForEach(numberOfImages.indices, id: \.self) { index in
if index == 0 {
Image("\(numberOfImages[index])")
.resizable()
.scaledToFill()
.overlay(
GeometryReader { proxy -> Color in
let minX = proxy.frame(in: .global).minX
DispatchQueue.main.async {
withAnimation(.default) {
self.offset = -minX
}
}
return Color.clear
}.frame(width: 0, height: 0)
,alignment: .leading
)
} else {
Image("\(numberOfImages[index])")
.resizable()
.scaledToFill()
.overlay(Color.black.opacity(0.2))
}
}//: ForEach
} //: TabView
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.overlay(
HStack(spacing:15) {
ForEach(numberOfImages.indices, id: \.self) { index in
Capsule()
.fill(Color.white)
.frame(width: getIndex() == index ? 20 : 7, height: 7)
}
}
//Smooth Sliding effect...
.overlay(
Capsule()
.fill(Color.white)
.frame(width: 20, height: 7)
.offset(x: getOffset())
, alignment: .leading
)
.padding(.bottom, UIApplication.shared.connectedScenes.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }.first { $0.isKeyWindow }?.safeAreaInsets.bottom)
.padding(.bottom, 10)
, alignment: .bottom
)
} //: Scrollview
.ignoresSafeArea()
} //: body
func getIndex() -> Int {
print("DEBUG: Current offset is: \(offset)")
print("DEBUG: Current getWidth is: \(getWidth())")
let progress = round(offset / getWidth())
let index = min(Int(progress), numberOfImages.count - 1)
print("DEBUG: Current index is: \(index)")
return index
}
func getOffset() -> CGFloat {
// spacing = 15
// Circle width = 7
// So total = 22
let progress = offset / getWidth()
return 22 * progress
}}
extension View {
func getWidth() -> CGFloat {
return UIScreen.main.bounds.width
}}
As you can see if i scroll to the 3rd picture, it stops calculating my offset. As my screen width is 390, i would expect the offset to be 780 (and 1170 after my 4th picture), but as you can see it stopped counting at 510.
Hope to hear from you all.