2016-10-26 123 views
4

如何使用Swift 3檢測方向改變?UIView框架在方向改變後沒有更新

我需要在更改後檢測它以計算幀大小。

編輯:

我問這個問題,因爲我需要重繪視圖的方向變化像這樣一個問題:Can't get background gradient to fill entire screen upon rotation

我不知道如何實現標記爲正確答案的答案。

我嘗試另一個答案

self.backgroundImageView.layer.sublayers?.first?.frame = self.view.bounds 

,但它不工作。

viewDidLoad()

let color1 = UIColor(red: 225.0/255.0, green: 210.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor 
     let color2 = UIColor(red: 255.0/255.0, green: 125.0/255.0, blue: 77.0/255.0, alpha: 1.0).cgColor 

     let gradientLayer = CAGradientLayer() 
     gradientLayer.colors = [color1, color2] 
     gradientLayer.locations = [ 0.0, 1.0] 
     gradientLayer.frame = self.view.bounds 

     self.view.layer.insertSublayer(gradientLayer, at: 0) 
+0

__A .__您可以確保創建正確的觀點,層次結構,儘量不要制動器,所支持的通知鏈iOS自動;或__B。__您可以訂閱'UIDeviceOrientationDidChangeNotification'並聽取方位的變化和更新您的自定義視圖時,它是必要的。 – holex

+0

看到我answer..it解決您的問題 –

回答

10

上述接受的答案返回幀大小不updating..You需要過渡完成後得到的幀大小。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 

     coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in 

      let orient = UIApplication.shared.statusBarOrientation 

      switch orient { 

      case .portrait: 

       print("Portrait") 

      case .landscapeLeft,.landscapeRight : 

       print("Landscape") 

      default: 

       print("Anything But Portrait") 
      } 

      }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in 
       //refresh view once rotation is completed not in will transition as it returns incorrect frame size.Refresh here   

     }) 
     super.viewWillTransition(to: size, with: coordinator) 

    } 
+1

我嘗試了一堆東西,但我找不到這將有更新的視角畫面的解決方案。完成處理程序在視圖框架解決問題之後執行並且您的答案非常有用的事實。 – harmeet07

6

添加此功能,並you'll檢測取向變化:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    if UIDevice.current.orientation.isLandscape { 
     print("Landscape") 
    } else if UIDevice.current.orientation.isPortrait { 
     print("Portrait") 
    } 
} 
+0

謝謝!它有效,但我有另一個問題,因爲我首先提出了這個問題。我更新了我的問題。你能檢查出來嗎? – user3847113

+0

嘗試'self.view.setNeedsLayout()'你'viewDidLoad' –

+0

'self.view.setNeedsLayout結束()'不工作。 – user3847113

5

要獲得方向變化回調您需要添加此通知

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) 

並且您需要實施此方法

func rotated() { 
    if(UIDeviceOrientationIsLandscape(UIDevice.current.orientation)) 
    { 
     print("landscape") 
    } 

    if(UIDeviceOrientationIsPortrait(UIDevice.current.orientation)) 
    { 
     print("Portrait") 
    } 
} 
0

嘗試transition.So你的觀點在此之前

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 
    if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { 

     print("Landscape mode called") 

     if UI_USER_INTERFACE_IDIOM() == .Pad { 
      print("Landscape mode in ipad"); 

     } 
     else 
     { 
      print("Landscape mode in Iphone ") 

     } 
    } else { 
     print("Portrait mode called") 
     if UI_USER_INTERFACE_IDIOM() == .Pad { 

      print("Portrait mode called in ipad") 
     } 
     else 
     { 
      print("Portrait mode called in iphone") 
     } 
    } 
} 
override func willRotateToInterfaceOrientation(toInterfaceOrientation:UIInterfaceOrientation, duration: NSTimeInterval) { 
    print("willRotateToInterfaceOrientation method called"); 
    //Here you can invalidateLayout() 
} 
+1

這是不正確的......使用viewWillTransition代替。 –

+0

@Anish웃它的工作me..you可以只是嘗試這個代碼 –

+1

它的工作原理,但viewWillTransition只調用時裝置轉動,但viewWillLayoutSubviews可以致電數次 –

2

這是我的解決方案基於以下要求:

(1)我的佈局需要改變根據其尺寸較大,高度或寬度。 (基本上是縱向或橫向,但在未來...?)

(2)我的應用程序是通用的,所以我不能考慮大小類或與它們相關的任何覆蓋。

(3)我的應用程序也有一個照片編輯擴展,所以UIApplication不可用。 (另外,landscapeLeft和landscapeRight等方向不適用於此類擴展名。)

注意:爲了完整性,我添加了AutoLayout的結構。

的UIViewController:

var p = [NSLayoutConstraint]() 
var l = [NSLayoutConstraint]() 
var initialOrientation = true 
var isInPortrait = false 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // set up all constraints, including common, portrait and landscape 
    setUpConstraints() 
} 

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 
    if initialOrientation { 
     initialOrientation = false 
     if view.frame.width > view.frame.height { 
      isInPortrait = false 
     } else { 
      isInPortrait = true 
     } 
     orientationChanged() 
    } else { 
     if view.orientationHasChanged(&isInPortrait) { 
      orientationChanged() 
     } 
    } 
} 

func orientationChanged() { 
    // this was split out because of other app-specific logic 
    view.setOrientation(p, l) 
} 

的UIView:

extension UIView { 

    public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool { 
     // always check against isInPortrait to reduce unnecessary AutoLayout changes! 
     if self.frame.width > self.frame.height { 
      if isInPortrait { 
       isInPortrait = false 
       return true 
      } 
     } else { 
      if !isInPortrait { 
       isInPortrait = true 
       return true 
      } 
     } 
     return false 
    } 
    public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) { 
     NSLayoutConstraint.deactivate(l) 
     NSLayoutConstraint.deactivate(p) 
     if self.bounds.width > self.bounds.height { 
      NSLayoutConstraint.activate(l) 
     } else { 
      NSLayoutConstraint.activate(p) 
     } 
    } 
}