誰かがiOS 8でポートレートとランドスケープのインターフェイスの向きを操作するための「正しい」または「最良の」アプローチを教えてもらえますか?その目的で使用したいすべての機能はiOS 8で非推奨になったようで、私の研究では明確でエレガントな代替手段は見つかりませんでした。私たちがポートレートモードかランドスケープモードかを判断するために、実際に幅と高さを調べることになっていますか?
たとえば、View Controllerでは、次の擬似コードをどのように実装する必要がありますか?
if we are rotating from portrait to landscape then
do portrait things
else if we are rotating from landscape to portrait then
do landscape things
Appleは、UIがレイアウトと外観を大幅に変更できるように、使用可能な画面スペースの大まかな尺度としてサイズクラスを使用することをお勧めします。縦向きのiPadには、横向きのiPadと同じサイズクラス(通常の幅、通常の高さ)があることを考慮してください。これは、2つの方向のUIが多少似ていることを意味します。
ただし、iPadでポートレートからランドスケープへの変更は十分に重要であるため、サイズクラスは変更されていませんが、UIを少し調整する必要があります。 UIViewController
のメソッドに関連するインターフェイスの向きは非推奨になったため、Appleでは、代わりにUIViewController
に次の新しいメソッドを実装することをお勧めします。
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// Code here will execute before the rotation begins.
// Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Place code here to perform animations during the rotation.
// You can pass nil or leave this block empty if not necessary.
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Code here will execute after the rotation has finished.
// Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]
}];
}
すばらしいです!これで、回転の開始直前と終了後にコールバックを取得できます。しかし、回転が縦向きか横向きかを実際に知ることはどうでしょうか?
Appleは、回転を単に親ビューのサイズの変更として考えることをお勧めします。つまり、iPadをポートレートからランドスケープにローテーションする際に、ルートレベルのビューをbounds.size
を{768, 1024}
から{1024, 768}
に変更するだけと考えることができます。これを知っているので、上のviewWillTransitionToSize:withTransitionCoordinator:
メソッドに渡されたsize
を使用して、ポートレートまたはランドスケープのどちらに回転しているかを判断する必要があります。
従来のコードを新しいiOS 8の方法にさらにシームレスに移行する方法が必要な場合は、UIViewで this simple category を使用することを検討してください。これは、ビューが「ポートレート」かどうかを判断するために使用できますまたはそのサイズに基づいた「風景」。
要点をまとめると:
viewWillTransitionToSize:withTransitionCoordinator:
コールバックを使用します。statusBarOrientation
(基本的にデバイスレベルのプロパティ)を使用して、「ポートレート」と「ランドスケープ」のビューをレイアウトするかどうかを決定しないでください。ステータスバーの方向は、アプリのまさにルートレベルに実際に存在するUIWindow
のようなものを処理するコードでのみ使用する必要があります。Smileyborgの非常に詳細な(そして受け入れられた)回答に基づいて、Swift 3を使用した適応を以下に示します。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil, completion: {
_ in
self.collectionView.collectionViewLayout.invalidateLayout()
})
}
そして、UICollectionViewDelegateFlowLayout
実装では、
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// retrieve the updated bounds
let itemWidth = collectionView.bounds.width
let itemHeight = collectionView.bounds.height
// do whatever you need to do to adapt to the new size
}
私は単に通知センターを使用します:
方向変数を追加します(最後に説明します)
//Above viewdidload
var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
ビューが表示されたときに通知を追加
override func viewDidAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
表示が消えたときに通知を削除
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil)
}
通知がトリガーされたときに現在の向きを取得
func orientationChanged (notification: NSNotification) {
adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
}
向き(縦/横)を確認し、イベントを処理します
func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
{
if(orientation != orientations) {
println("Portrait")
//Do Rotation stuff here
orientations = orientation
}
}
else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
{
if(orientation != orientations) {
println("Landscape")
//Do Rotation stuff here
orientations = orientation
}
}
}
オリエンテーション変数を追加する理由は、物理デバイスでテストするとき、デバイスが回転するときだけでなく、デバイス内の小さな動きごとにオリエンテーション通知が呼び出されるためです。 varおよびifステートメントを追加すると、反対方向に切り替わった場合にのみコードが呼び出されます。
UIの観点から、サイズクラスを使用することは、さまざまな向き、サイズ、スケールのインターフェイスを処理するためのAppleの推奨アプローチであると考えています。
セクションを参照してください:Traits Describe Desize Size Class and Scale of the Interfacehere: https://developer.Apple.com/library/ios/releasenotes/General/ WhatsNewIniOS/Articles/iOS8.html
「iOS 8には、画面のサイズと向きをより柔軟に扱うための新しい機能が追加されています。」
これも良い記事です: https://carpeaqua.com/thinking-in-terms-of-ios-8-size-classes/
EDIT更新されたリンク: https://carpeaqua.com/2014/06/14/thinking-in-terms-of- ios-8-size-classes / (クレジット:Koen)