xcode でインターフェイス ビルダーを使用し、.xib ファイルを 1 つだけ使用して、横向きと縦向きの間で回転するときに代替レイアウトを作成するにはどうすればよいですか?
さまざまなレイアウトの図を参照してください
注意してください。緑のビュー/エリアには、横向きでは水平に流れる 3 つのアイテムが含まれ、縦向きでは、これらの 3 つのアイテムが緑のビュー/エリア内で垂直に流れます。
xcode でインターフェイス ビルダーを使用し、.xib ファイルを 1 つだけ使用して、横向きと縦向きの間で回転するときに代替レイアウトを作成するにはどうすればよいですか?
さまざまなレイアウトの図を参照してください
注意してください。緑のビュー/エリアには、横向きでは水平に流れる 3 つのアイテムが含まれ、縦向きでは、これらの 3 つのアイテムが緑のビュー/エリア内で垂直に流れます。
Apple の設計に反するため、自動的にサポートする方法はありません。両方の向きをサポートする 1 つの ViewController が必要です。
しかし、本当にそうしたい場合は、ローテーション イベントで xib をリロードし、別の nib ファイルをロードする必要があります。
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[[NSBundle mainBundle] loadNibNamed:[self nibNameForInterfaceOrientation:toInterfaceOrientation] owner:self options:nil];
[self viewDidLoad];
}
- (NSString*) nibNameForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
NSString *postfix = (UIInterfaceOrientationIsLandscape(interfaceOrientation)) ? @"portrait" : @"landscape";
return [NSString stringWithFormat:@"%@-%@", NSStringFromClass([self class]), postfix];
}
そして、「横向き」と「縦向き」で後置固定された 2 つの nib ファイルを作成します。
@MeXx のソリューションは気に入っていますが、2 つの異なるビュー階層をメモリに保持するというオーバーヘッドがあります。また、サブビューに変化する状態 (色など) がある場合は、階層を切り替えるときにそれをマッピングする必要があります。
別の解決策は、自動レイアウトを使用して、各方向の各サブビューの制約を交換することです。これは、両方の方向のサブビュー間に 1:1 のマッピングがある場合に最適です。
当然のことながら、IB を使用して各方向のレイアウトを視覚的に定義します。私の計画では、@MeXx が規定することを実行する必要がありますが、ペン先がロードされたら両方の制約セットを保存し ( awakeFromNib
)、レイアウトに正しいセットを再適用するメカニズムを作成します ( viewWillLayoutSubviews
)。制約をスクレイピングして保存したら、セカンダリ ビュー階層を破棄できます。(制約はビュー固有であるため、実際のサブビューに適用する新しい制約を作成する可能性があります)。
申し訳ありませんが、コードはありません。あくまで現段階での予定です。
最後の注意 - ストーリーボードでは、ビュー コントローラーのメイン ビューの外側にあるビューを記述するのが面倒なので、これはすべてストーリーボードよりも xib の方が簡単です (それ以外の場合は編集する PITA であるため、これは望ましいことです)。ブラック!
ios8 と XCode 6 の今後の新機能を反映するために、新しい回答を追加したいと思います。
最新の新しいソフトウェアで、Apple はサイズ クラスを導入しました。これにより、使用している画面のサイズと向きに基づいてストーリーボードをインテリジェントに適応させることができます。上記のドキュメントまたは WWDC 2014 セッションビルディング アダプティブ アプリ with UIKitを参照することをお勧めしますが、言い換えてみます。
サイズ クラスが有効になっていることを確認します。
ストーリーボード ファイルが正方形になっていることがわかります。ここで基本的なインターフェースを設定できます。インターフェイスは、有効なすべてのデバイスと向きに合わせてインテリジェントにサイズ変更されます。
画面の下部に、yAny xAny というボタンが表示されます。これをクリックすると、横向きと縦向きなど、サイズ クラスを 1 つだけ変更できます。
上記のドキュメントを読むことをお勧めしますが、使用するストーリーボードは 1 つだけなので、これがお役に立てば幸いです。
ストーリーボードによる解決 [ios7]。メイン ビュー コントローラー内には、タブ バー コントローラーを含めることができるコンテナー ビューがあります。タブ バー コントローラー内には、2 つのタブがあります。1 つのタブは縦向きのコントローラー用で、もう 1 つのタブは横向きモードのコントローラー用です。
メイン ビュー コントローラーは、次の関数を実装します。
#define INTERFACE_ORIENTATION() ([[UIApplication sharedApplication]statusBarOrientation])
@interface MainViewController ()
@property(nonatomic,weak) UITabBarController *embeddedTabBarController;
@end
@implementation MainViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"embedContainer"])
{
self.embeddedTabBarController = segue.destinationViewController;
[self.embeddedTabBarController.tabBar setHidden:YES];
}
}
- (void) adaptToOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
[self.embeddedTabBarController setSelectedIndex:1];
}
else
{
[self.embeddedTabBarController setSelectedIndex:0];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
[self adaptToOrientation:interfaceOrientation];
}
- (void) viewWillAppear:(BOOL)animated
{
[self adaptToOrientation:INTERFACE_ORIENTATION()];
}
ストーリーボードのセグエ リンクの名前は「embedContainer」にする必要があります。
横向きと縦向きの両方の場合で、コンテナー ビューが親ビューを満たすようにサイズ変更できることを確認します。
実行時に同じコントローラーの 2 つのインスタンスが同時に存在することに注意してください。
プログラムによるサイズ変更
まったく同じ状況のアプリがあります。私のNIBには、縦向きのレイアウトがあります。もう 1 つのレイアウトは、プログラムによって実行されます。プログラムでいくつかのサイズを指定することはそれほど難しくないため、2 つの NIB を維持する必要はありません。
フレームを設定してプログラムでビューの変更を実行すると、アニメーションが発生することに注意してください (または、アニメーションを使用して簡単に作成できます)。これにより、どのコンポーネントがどの位置に移動したかについての貴重なフィードバックがユーザーに提供されます。2 番目のビューをロードするだけでは、この利点が失われます。UI の観点から、別のビューをロードすることは良い解決策ではないと思います。
2 つの ViewController を使用する
2 つの ViewController を使用したい場合は、Apple がその開発者向けドキュメントでその方法を説明しています。
プログラムで実行したい場合は、メソッドに再配置コードを追加できますdidRotateFromInterfaceOrientation
。
例
ViewController にメソッドを追加しました。
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self adjustLayoutToOrientation];
}
その後、レイアウトの調整を実施。以下に例を示します (コードは私のアプリに固有のものですが、スーパービューのサイズを読み取り、そこからサブビューのフレームを計算できます。
- (void)adjustLayoutToOrientation
{
UIInterfaceOrientation toInterfaceOrientation = self.interfaceOrientation;
bool isIPhone = !([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
[self adjustViewHeight];
[self adjustSubviewsToFrame: [mailTemplateBody.superview.superview frame]];
CGRect pickerViewWrapperFrame = pickerViewWrapper.frame;
if(isIPhone) {
pickerViewWrapperFrame.origin.x = 0;
pickerViewWrapperFrame.size.height = keyboardHeight;
pickerViewWrapperFrame.origin.y = [self view].frame.size.height-pickerViewWrapperFrame.size.height;
pickerViewWrapperFrame.size.width = [self view].frame.size.width;
}
else {
pickerViewWrapperFrame = pickerView.frame;
}
// MORE ADJUSTMENTS HERE
}
ライブラリGPOrientationを使用できます。ここにリンクがあります