5

Using Swift 5.3.2, Xcode 12.4, iOS 14.4,

I am trying to make a simple Page-TabView in SwiftUI (see below code-excerpt).

When rotating to Landscape or back to Portrait, there is a problem (see video):

Whenever I rotate my iPhone, the TabView "jumps" to a random tab-number.

Why is this ?

What can I do make the TabView keep the current tab-number when rotating ?

(I am using an iPhoneX)

There seem more issues with the new iOS14 TabView's PageControl function as decribed here. (Maybe the "random tab-number" when rotating the device is related to the layout-issue described)

enter image description here

import SwiftUI

@main
struct MyApp: App {
    
    var body: some Scene {
        WindowGroup {
            TabView {
                Text("1")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.pink)
                Text("2")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.yellow)
                Text("3")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.green)
                Text("4")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.blue)
            }
            .tabViewStyle(PageTabViewStyle())
        }
    }
}
oguz ismail
  • 1
  • 16
  • 47
  • 69
iKK
  • 6,394
  • 10
  • 58
  • 131
  • 2
    I have the same problem. – 蘇哲聖 Jul 25 '21 at 09:19
  • Yeah, lots of unsolvable issues with landscape TabView. All problems solved when using a standard UIPageViewController wrapped with UIViewControllerRepresentable. – noobular Aug 06 '21 at 18:58
  • Can you please add a full example of your working `UIPageViewController wrapped with UIViewControllerRepressentable` ?? – iKK Oct 16 '21 at 08:08
  • 1
    @iKK Here Apple's tutorial https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit – nurmat Nov 03 '21 at 10:20

1 Answers1

0

One of a solution is to set back to active tab item using custom view modifier for example, this. It seems jump happens after rotation finish, so delayed timer could be used:

// Implement your rotation change modifier
.onChange(of: isLandscape) { _ in
    if selectedTab > 0 { // Do not reset for first element
        let beforeIndex = selectedTab
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
            selectedTab = beforeIndex
        }
    }
}

And the result is:

enter image description here

Full source code here

nurmat
  • 361
  • 3
  • 11
  • hmm, I am not convinced that we have to create delay-timers. My example screens are very simplicistic - and my real-wold page-view is much more complex in terms of rendering aspects. And in a real-world application, there are always nasty dependencies like network-calls that are of different speed, etc. And your solution is o.k. (and I thank you for putting the effort). But I think the delay-solution is only a hack for something that should be there right out of the box from Apple. Is a hacky delay-solution really the only solution in mid 2022 ?? – iKK Jul 16 '22 at 14:26
  • Another solution could be to use LazyHStack instead of TabView. But in this case you have to implement a lot of features by own – nurmat Aug 01 '22 at 06:32