2016-10-26 21 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 

を試してみましたが、それは働いていません。私は

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

私の答えを参照してください..itはあなたの問題を解決します –

答えて

10

を試してみてくださいtransition.Soあなたのビューが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

を持ってviewDidLoad()

この機能を追加し、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

'viewDidLoad'の最後に' self.view.setNeedsLayout() 'を実行してください。 –

+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

上記受け入れ答えこの

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このコードを試してみてください。 –

+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) 
     } 
    } 
} 
関連する問題