0

I want to rotate my view so that it changes its frame and covers the entire screen on rotation. I've tried all the types of rotations along with different anchors. This was working perfectly fine in iOS 13 but inside iOS 14 there is a strange gap between the view and the margin.

Regular View

When Entered Full Screen

struct ContentView: View {
    
    @State private var isFullScreen = false
    
    var body: some View {
        NavigationView {
            GeometryReader { geometry in
                ZStack(alignment: .center) {

                    VStack(spacing: 0) {
                            HStack(alignment: .top)
                            {
                                Spacer(minLength: 0)
                                ZStack(alignment: Alignment(horizontal: .trailing, vertical: .center)) {
                                    RoundedRectangle(cornerRadius: 0)
                                        .foregroundColor(Color.yellow)
                                        
                                    
                                    VStack {
                                        Button(action: {
                                            self.isFullScreen.toggle()
                                        }, label: {
                                            Text("FS")
                                    })
                                        
                                    }
                                }
                                .frame(width: self.isFullScreen ? geometry.size.height : geometry.size.width, height: self.isFullScreen ? geometry.size.width : geometry.size.height / 3)
                                .rotation3DEffect(
                                    Angle(degrees: isFullScreen ? -90 : 0),
                                    axis: (x: 0.0, y: 0, z: 1.0),
                                    anchor: .bottom,
                                    anchorZ: 0.0,
                                    perspective: 1.0
                                )   
                            }
                    }
                 
                }.background(Color.red)
                .navigationBarHidden(self.isFullScreen)
                .navigationBarTitle(self.isFullScreen ? "" : "Demo", displayMode: .inline)
                
            }
        }.navigationViewStyle(StackNavigationViewStyle())

    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
Rish
  • 1
  • 1
  • 1

1 Answers1

0

There should not be anything wrong with the size of the RoundedRectangle.

From what I have tried out, it is the rotation anchor that caused this problem. You may see it by manually setting a .offset() modifier on your ZStack which contains the RoundedRectangle.

Here is why the gap appears:

When you rotate your view with anchor set to .bottom, you are rotating counter-clockwise around the bottom center of your ZStack which contains the RoundedRectangle.

At the mean time, your are expanding your ZStack with new values of width and height.

In SwiftUI (iOS 14), when views are given a larger size after being rendered for the first time, they expand from their original top-left position toward the bottom-right.

When that happens during your rotation, the original height of your ZStack got rotated to the left side of your screen, with the original bottom center anchor fixed at the center of your screen. The added size (geometry.size.width - geometry.size.height/3) is grown from the center vertical line of your device screen.

Example (on an iPhone X screen, width: 375, height(safe area): 690): Before rotation: Rectangle is of vertical size: 230, horizontal size: 375, center align with screen. After rotating around bottom center of rectangle: Rectangle is of vertical size 690, horizontal size 375, center no longer align with screen. Count from the screen center, Rectangle has 230 pixels to the left, and (375 - 230 =) 145 to the right. The gap therefore is of size (375/2 - 145 =) 42.5

Therefore, the gap exists after the rotation, while the RoundedRectangle seems shifted to the left for a few pixels.

It's worth trying out yourself to figure out the actual situation. Thank you.

TonyTang
  • 11
  • 2
  • I tried offsetting as you suggested and it even fixed it on a single device resolution but on different devices, it has different offset calculations, which cannot be fixed even with the Geometry Reader. Is there another solution/workaround for this ? I also gave it a shot by trying out with every possible anchor but still wasn't able to align it correctly – Rish Sep 22 '20 at 04:19
  • I would suggest not using rotation concurrently with size changes in SwiftUI... To be honest, the way the SwiftUI renders UI changes can vary drastically from version to version, and there are still a lot of bugs floating around even in the latest released version of iOS 14 SDK. I would suggest using size changes only (without the rotation) if possible. Or try to use UIKit and wrap it as a SwiftUI view using UIViewRepresentable if you insist on the rotation effect. – TonyTang Sep 23 '20 at 06:18