How to get TabView offset in SwiftUI

Viewed 607
struct FooView: View {
    @State private var offset: CGFloat = 0

    var body: some View {
        NavigationView {
            TabView {
              VStack {
                Text("Tab 1")
              }
              VStack {
                Text("Tab 2")
              }
            }
            .SomeWatchOffsetMethod(of: offset) { value in
              // I want to get horizontal offset when TabView Scrolling.
              offset = value
            }
        }
    }
}

I want to get horizontal offset when TabView Scrolling in SwiftUI.

There are something like that in UIKit.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
  parent.offset = scrollView.contentOffset.x
}
1 Answers

To track an offset of any view, as well as views of TabView you can use Overlay + GeometryReader

Add an OffsetProxy as an overlay to a view that offset you are interested in

struct OffsetProxy: View {
    var body: some View {
        GeometryReader { proxy in
            Color.clear
                .preference(key: OffsetKey.self, value: proxy.frame(in: .global).minX)
        }
    }
}

Then you can subscribe to listen the offset changes in onPreferenceChange

struct FooView: View {
    @State private var offset: CGFloat = 0

    var body: some View {
        NavigationView {
            TabView {
                VStack {
                    Text("Tab")
                }
                .overlay(
                    OffsetProxy()
                )
                .onPreferenceChange(OffsetKey.self) { offset in
                    self.offset = offset
                }
            }
        }
    }
}
struct OffsetKey: PreferenceKey {
    static var defaultValue: CGFloat = 0

    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}
Related