19

我所試圖做的:由母公司 - 視圖 - 控制器管理應該無法旋轉子視圖控制器旋轉,同時父視圖控制器不

父視圖。

子視圖是由兒童視圖控制器管理就會以到所有方向。


enter image description here

enter image description here


我曾嘗試:

ParentViewController

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
    return .Portrait 
} 

override func shouldAutorotate() -> Bool { 
    return true 
} 

fun addChildViewController() { 
    let storyBoard = UIStoryboard(name: "Main", bundle: nil) 
    self.childViewController = storyBoard("Child View Controller") as? ChildViewController 
    self .addChildViewController(self.childViewController!) 
    self.childViewController! .didMoveToParentViewController(self) 
    self.view .addSubview(self.childViewController!.view) 
    self.childViewController!.view.frame = CGRectMake (40, 200, 400, 250) 
} 

ChildViewController

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
    return .All 
} 

override func shouldAutorotate() -> Bool { 
    return true 
} 

在Xcode部署信息支撐取向被設置爲四個。

我會得到什麼:

視圖的旋轉沒有。如果我將父級的旋轉設置爲全部,則所有視圖一起旋轉。所以這是全部或沒有。


UPDATE

,當我試圖把一個觀察員UIDeviceOrientationDidChangeNotification和使用UIDevice.currentDevice()。方向用CGAffaineTransformMakeRotate旋轉childView,我得到想要的結果。但是,即,如果我旋轉到橫向,並嘗試拉下通知中心(或者如果我得到系統通知),它仍然處於縱向方向(因爲應用程序本身仍然保留在縱向中),旋轉childView旋轉回肖像狀態欄/通知/通知中心。

股票iOS相機應用程序是我可以提供的最好的例子。主畫布不旋轉到不同的方向,但狀態欄在幕後旋轉以遵守設備旋轉。此外,子視圖也會自我旋轉以表達不同的傾向。我試圖實現此行爲....

+1

不知道這是否會起作用,只是把它當作一個想法。我肯定會設置應用程序只支持一個(人像)方向,然後我會嘗試檢測設備的旋轉(而不是屏幕),並通過在屏幕中間手動旋轉視圖來響應該設置。我猜'viewWillTransition(to:with:)'不起作用,所以你需要找到一個合適的解決方案。 – Andrej

+0

你的意思是使用CGAffineTransform之類的東西進行旋轉? – Gizmodo

+1

是的,完全是CGAffineTransform。你有一個有趣的情況。我很樂意幫忙,並且試着寫一些代碼來解決這個問題,但是恐怕我會很安靜,所以我不能在這裏弄髒我的手。 – Andrej

回答

1

做一個示範項目,經過多次來回與蘋果他們的自我,並指向同樣的鏈接Technical Q&A QA1890,我不得不用流動的方式做到這一點:

MotherViewController

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 

     super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 

     coordinator.animateAlongsideTransition({(context: UIViewControllerTransitionCoordinatorContext) -> Void in 
      let deltaTransform: CGAffineTransform = coordinator.targetTransform() 
      let deltaAngle: CGFloat = atan2(deltaTransform.b, deltaTransform.a) 
      var currentRotation: CGFloat = self.mainView.layer.valueForKeyPath("transform.rotation.z") as! CGFloat 

      // Adding a small value to the rotation angle forces the animation to occur in a the desired direction, preventing an issue where the view would appear to rotate 2PI radians during a rotation from LandscapeRight -> LandscapeLeft. 
      currentRotation += -1 * deltaAngle + 0.0001 
      self.mainView.layer.setValue(currentRotation, forKeyPath: "transform.rotation.z") 

      }, completion: {(
       context: UIViewControllerTransitionCoordinatorContext) -> Void in 
       // Integralize the transform to undo the extra 0.0001 added to the rotation angle. 
       var currentTransform: CGAffineTransform = self.mainView.transform 
       currentTransform.a = round(currentTransform.a) 
       currentTransform.b = round(currentTransform.b) 
       currentTransform.c = round(currentTransform.c) 
       currentTransform.d = round(currentTransform.d) 
       self.mainView.transform = currentTransform 
     }) 
    } 

MainViewController

NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name:UIDeviceOrientationDidChangeNotification, object: nil) 

func orientationChanged (notification: NSNotification){ 
     switch UIDevice.currentDevice().orientation { 
     case .Portrait: 
      self.rotateChildViewsForOrientation(0) 
     case .PortraitUpsideDown: 
      self.rotateChildViewsForOrientation(0) 
     case .LandscapeLeft: 
      self.rotateChildViewsForOrientation(90) 
     case .LandscapeRight: 
      self.rotateChildViewsForOrientation(-90) 
     default: 
      print ("Default") 
       } 
    } 

這似乎旋轉子視圖的同時保持主視圖靜態的。此外,該應用程序似乎知道正確的方向時,通知進來(因爲母親的看法實際上在幕後旋轉)。

特別感謝jameskWarif Akhand仙人所有幫助!

+0

這似乎並不適用於我,如http://stackoverflow.com/questions/42778355/why-am-i-seeing-a-glitch-in-the-counter-rotation-animation中所述想法爲什麼? –

4

在相機應用實現的效果類似於使用以下的組合:

技術說明中解釋說,自轉的底層實現涉及將直接轉換到應用程序的窗口:

自轉,通過施加旋轉來實現轉換爲應用程序的窗口時,系統確定界面必須旋轉。窗口然後調整其新方向的界限,並通過調用每個視圖控制器和呈現控制器的方法在視圖控制器層次結構中向下傳播此更改。

請注意,相機應用程序不會選擇退出自轉:使用相機應用程序時,通知中心和控制中心的方向反映設備的方向。這只是在相機應用程序中的特定視圖,似乎選擇退出自動旋轉。實際上,this answer暗示這樣的應用通常利用由諸如AVCaptureVideoPreviewLayerAVCaptureConnection的AVFoundation類提供的videoGravityvideoOrientation屬性。

您應該採取的方法取決於您是否只想停止父視圖的旋轉,或者是否想要停止容器視圖控制器(如UINavigationController)旋轉(即鎖定設備方向)。

如果前者使用技術說明中描述的技術修復父視圖的方向,並且(對於iOS 9)在UIStackView中旋轉子視圖並使用axis屬性重新排列設備旋轉上的子視圖,或(對於iOS 8)手動旋轉設備旋轉上的子視圖(關於其參見this answerthis sample code)。

如果是後者,您採取的方法是正確的。有關示例代碼,請參閱this answer。您需要分享您的代碼和更多關於視圖控制器層次結構的信息,以便我們診斷涉及Notification Center的怪癖。

附錄:爲什麼要shouldAutorotatesupportedInterfaceOrientations電話都沒有被傳播到子視圖控制器在Technical Q&A QA1688解釋原因:

與iOS 6中,只有最上面的視圖控制器(開始沿着UIApplication對象)參與決定是否響應於設備的方向改變而旋轉。通常情況下,顯示您內容的視圖控制器是UINavigationController,UITabBarController或子容器視圖控制器的子項。您可能會發現自己需要爲容器視圖控制器創建子類,以修改其supportedInterfaceOrientationsshouldAutorotate方法返回的值。

在Swift中,您可以override those methods by using extensions

+0

很好的回覆!我仍在閱讀鏈接。正如我在下面提到的,我遇到了使用viewWillTransitionToSize的問題:withTransitionCoordinator:因爲我希望motherView在childView旋轉時不旋轉。如果motherView根本不旋轉,viewWillTransitionToSize:withTransitionCoordinator:不會在它自己內被調用。 – Gizmodo

+0

這裏的技巧:不要從'shouldAutorotate'返回'false'。使用技術說明中顯示的技術來阻止motherView旋轉 - 這不會干擾'viewWillTransitionToSize:' - 並使用後者(或'viewWillLayoutSubviews')來相應地旋轉子視圖。 – jamesk

+0

不幸的是仍然努力使其工作.... – Gizmodo

2

距離Ios顯影劑庫Technical Q&A

自轉通過施加旋轉變換應用程序的窗口時,系統確定該接口必須旋轉實現。窗口然後調整其新方向的界限,並通過視圖控制器層次結構通過調用每個視圖控制器和呈現控制器的-viewWillTransitionToSize:withTransitionCoordinator:方法向下傳播此更改。該方法的調用提供了一個包含窗口當前變換和新變換增量的過渡協調器對象,可以通過向過渡協調器發送-targetTransform消息來檢索該變換。您的視圖控制器或表示控制器可以派生出適當的逆變換並將其應用於目標視圖。這將使窗口轉換對該特定視圖的影響無效,並且使界面的其餘部分正常旋轉時視圖在當前方向上保持固定的外觀。

也就是說,如果你有一個命名視圖noRotatingView

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    noRotatingView.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)) 
} 

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) 

    coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in 

     let deltaTransform = coordinator.targetTransform() 
     let deltaAngle = atan2f(Float(deltaTransform.b), Float(deltaTransform.a)) 

     var currentRotation = self.noRotatingView.layer.valueForKeyPath("transform.rotation.z")?.floatValue 

     // Adding a small value to the rotation angle forces the animation to occur in a the desired direction, preventing an issue where the view would appear to rotate 2PI radians during a rotation from LandscapeRight -> LandscapeLeft. 
     currentRotation = currentRotation! + (-1 * Float(deltaAngle)) + 0.0001 
     self.noRotatingView.layer.setValue(currentRotation, forKeyPath:"transform.rotation.z") 

     }) { (UIViewControllerTransitionCoordinatorContext) -> Void in 

      var currentTransform = self.noRotatingView.transform; 
      currentTransform.a = round(currentTransform.a); 
      currentTransform.b = round(currentTransform.b); 
      currentTransform.c = round(currentTransform.c); 
      currentTransform.d = round(currentTransform.d); 
      self.noRotatingView.transform = currentTransform; 
    } 
} 

我試過在https://github.com/rishi420/TestCameraRotation

+0

你的答案很棒!看看你的示例代碼,我仍然會遇到主要問題,即使我在查看Apple的技術文檔時仍然遇到以下問題:MotherView不旋轉,ChildView旋轉。如果包含視圖根本不旋轉,則不會調用viewWillTransitionToSize方法。這是我仍然卡在... – Gizmodo

+0

@gizmodo我認爲母親的觀點旋轉在iOS相機應用程序。因此通知中心和控制中心旋轉。如果你想鎖定母視圖,你可以看到[RotateButton](https://github.com/rishi420/RotateButton)。 –

+1

您的TestCameraRotation + RotateButton的組合在這一點上是最有意義的。 1.將MainView放入另一個視圖中,並使用viewWillTransitionToSize停止旋轉。 1.使用設備方向KVO旋轉childView。 – Gizmodo

相關問題