muapps

iOSアプリ開発で得られた知見をメモ代わりに投稿します。

端末の向きに合わせて一部のViewのみ移動&回転させる

移動

複数の制約を設定しpriorityを変更することで制約を切り替える

@IBOutlet weak var targetViewPortraitCenterX: NSLayoutConstraint! // 初期priority: 999
@IBOutlet weak var targetViewPortraitCenterY: NSLayoutConstraint! // 初期priority: 999
@IBOutlet weak var targetViewLandscapeCenterX: NSLayoutConstraint! // 初期priority: 750
@IBOutlet weak var targetViewLandscapeCenterY: NSLayoutConstraint! // 初期priority: 750
targetViewPortraitCenterX.priority = UILayoutPriority(750)
targetViewPortraitCenterY.priority = UILayoutPriority(750)
targetViewLandscapeCenterX.priority = UILayoutPriority(999)
targetViewLandscapeCenterY.priority = UILayoutPriority(999)
回転
// 90°回転させる
let angle = 90 * CGFloat.pi / 180
self.targetView.transform = CGAffineTransform(rotationAngle: angle)
全体
class ExampleViewController: UIViewController {

    @IBOutlet weak var targetView: UIView!
    @IBOutlet weak var targetViewPortraitCenterX: NSLayoutConstraint! // 初期priority: 999
    @IBOutlet weak var targetViewPortraitCenterY: NSLayoutConstraint! // 初期priority: 999
    @IBOutlet weak var targetViewLandscapeCenterX: NSLayoutConstraint! // 初期priority: 750
    @IBOutlet weak var targetViewLandscapeCenterY: NSLayoutConstraint! // 初期priority: 750

     override func viewDidLoad() {
         super.viewDidLoad()
         // 端末の向き検知
         NotificationCenter.default.addObserver(self, selector: #selector(self.changedOrientation), name: UIDevice.orientationDidChangeNotification, object: nil)
     }

     @objc func changedOrientation() {
          var angle: CGFloat = 0.0
          // 座標移動
          let orientation = UIDevice.current.orientation
          if orientation == .portrait {
               self.targetViewPortraitCenterX.priority = UILayoutPriority(999)
               self.targetViewPortraitCenterY.priority = UILayoutPriority(999)
               self.targetViewLandscapeCenterX.priority = UILayoutPriority(750)
               self.targetViewLandscapeCenterY.priority = UILayoutPriority(750)
               angle = 0.0
          } else if orientation == .landscapeLeft {
               self.targetViewPortraitCenterX.priority = UILayoutPriority(750)
               self.targetViewPortraitCenterY.priority = UILayoutPriority(750)
               self.targetViewLandscapeCenterX.priority = UILayoutPriority(999)
               self.targetViewLandscapeCenterY.priority = UILayoutPriority(999)
               angle = 90 * CGFloat.pi / 180
          }
          // 回転
          UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: {
               self.targetView.transform = CGAffineTransform(rotationAngle: angle)
          })
     }
}
さいごに

上の例はStoryboardを使用しているがコードでUIを組んでいても同じような方法でできると思う。
方法は他にもあるかもしれない。