Skip to content

Instantly share code, notes, and snippets.

@nurmaj
Last active September 20, 2022 05:18
Show Gist options
  • Save nurmaj/ee83e454818e777fcb49235d4f0706c0 to your computer and use it in GitHub Desktop.
Save nurmaj/ee83e454818e777fcb49235d4f0706c0 to your computer and use it in GitHub Desktop.
SwiftUI TabView Orientation change fix
import SwiftUI
struct TabViewRotationFix: View {
@State
private var selectedTab = Int.zero
@State
private var isLandscape = false
var body: some View {
GeometryReader { proxy in
ScrollView {
TabView(selection: $selectedTab) {
Color.yellow
.frame(width: proxy.size.width, height: proxy.size.height)
.ignoresSafeArea()
.overlay(Text("0").font(.largeTitle).fontWeight(.bold))
.tag(0)
Color.blue
.frame(width: proxy.size.width, height: proxy.size.height)
.ignoresSafeArea()
.overlay(Text("1").font(.largeTitle).fontWeight(.bold))
.tag(1)
Color.gray
.frame(width: proxy.size.width, height: proxy.size.height)
.ignoresSafeArea()
.overlay(Text("2").font(.largeTitle).fontWeight(.bold))
.tag(2)
}
.frame(width: proxy.size.width, height: proxy.size.height)
.overlay(Text(isLandscape ? "Landscape" : "Portrait").font(.title).padding(.bottom, 40), alignment: .bottom)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
.onChange(of: isLandscape) { isLandscape in
if selectedTab > 0 { // Do not reset for first element
let beforeIndex = selectedTab
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
selectedTab = beforeIndex
}
}
}
// Implement your rotation change modifier
.onRotate { newOrientation in
isLandscape = newOrientation == .landscapeLeft || newOrientation == .landscapeRight
}
}
.frame(width: proxy.size.width, height: proxy.size.height)
.foregroundColor(.white)
}
.edgesIgnoringSafeArea(.all)
}
}
extension View {
func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
self.modifier(DeviceRotationViewModifier(action: action))
}
}
struct DeviceRotationViewModifier: ViewModifier {
let action: (UIDeviceOrientation) -> Void
func body(content: Content) -> some View {
content
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
action(UIDevice.current.orientation)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment