Autosize(2)~コードによる変更

2010. 08. 22
前回の『Autosize(1)~Autosizing』は、Interface BuilderのAutosizingを使って、ランドスケープ時のオブジェクトパーツのレイアウトを自動調整しました。

しかしシステムによる自動調整は簡単で便利ですが、必ずしも望む結果にはなりません。

本書でも例としてボタンのサイズを125x125ピクセルにした場合の例を示しています。

各ボタンの位置とサイズを下表のように変更してみます。

 XYWH
Rounded Rect Button (1)2020125125
Rounded Rect Button (2)17520125125
Rounded Rect Button (3)20168125125
Rounded Rect Button (4)175168125125
Rounded Rect Button (5)20315125125
Rounded Rect Button (6)175315125125

712

ランドスケープモードにすると高さが足りず、パーツが重なってしまいます。

713

ちなみに各ボタンのサイズをバネで自動調整すると下図のようになります。

714

これで構わない場合はいいのですが、パーツサイズを変えたくなかったり、中央の空間が気になる場合は手動で調整することができます。


●アウトレットの宣言

AutosizeViewController.hを開き、ボタン6個分のアウトレットとプロパティを宣言します。
(太字が追加した部分)

#import <UIKit/UIKit.h>

@interface AutosizeViewController : UIViewController {
    IBOutlet UIButton *button1;
    IBOutlet UIButton *button2;
    IBOutlet UIButton *button3;
    IBOutlet UIButton *button4;
    IBOutlet UIButton *button5;
    IBOutlet UIButton *button6;
}
@property (nonatomic, retain) UIView *button1;
@property (nonatomic, retain) UIView *button2;
@property (nonatomic, retain) UIView *button3;
@property (nonatomic, retain) UIView *button4;
@property (nonatomic, retain) UIView *button5;
@property (nonatomic, retain) UIView *button6;

@end

715


●画像の追加とアウトレットの接続

ただのRound Rect Buttonでは味気ないので画像を追加してみます。
(機能とは関係ありませんので省略しても構いません)

Resourcesに125x125のPNGファイルを6個追加します。

716

Interface Builderに移り、InspectorウィンドウのAttributesタブで『Title』の数字を削除し、『Image』で画像を選択します。

717

画像を入れ終わったらDocumentsウィンドウでFile's Ownerを選択し、InspectorウィンドウでConnectionsタブを開き、Round Rect Buttonとアウトレットを接続します。

718


●回転時のレイアウトのコード記述

ポートレートおよびランドスケープ時における、6つのボタンのレイアウト切り替えをコードで記述します。
(太字が追加した部分)

#import "AutosizeViewController.h"

@implementation AutosizeViewController

@synthesize button1;
@synthesize button2;
@synthesize button3;
@synthesize button4;
@synthesize button5;
@synthesize button6;

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
        duration:(NSTimeInterval)duration {
    UIInterfaceOrientation toInterfaceOrientation = self.interfaceOrientation;

    [UIView beginAnimations:@"move buttons" context:nil];

    if (toInterfaceOrientation == UIInterfaceOrientationPortrait ||
        toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
        button1.frame = CGRectMake( 20, 20, 125, 125);
        button2.frame = CGRectMake(175, 20, 125, 125);
        button3.frame = CGRectMake( 20, 168, 125, 125);
        button4.frame = CGRectMake(175, 168, 125, 125);
        button5.frame = CGRectMake( 20, 315, 125, 125);
        button6.frame = CGRectMake(175, 315, 125, 125);
    }
    else {
        button1.frame = CGRectMake( 20, 20, 125, 125);
        button2.frame = CGRectMake(20, 155, 125, 125);
        button3.frame = CGRectMake(177, 20, 125, 125);
        button4.frame = CGRectMake(177, 155, 125, 125);
        button5.frame = CGRectMake(328,  20, 125, 125);
        button6.frame = CGRectMake(328, 155, 125, 125);
    }
    [UIView commitAnimations];
}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait ||
        interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)dealloc {
    [button1 release];
    [button2 release];
    [button3 release];
    [button4 release];
    [button5 release];
    [button6 release];
    [super dealloc];
}

@end

719

最初に6つのボタンのプロパティの実装、最後にdeallocで解放を行っています。

shouldAutorotateToInterfaceOrientation:メソッドは前回実装したままです。

willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:メソッドは、ユーザインターフェイスが回転する際の後半開始時に呼び出されるメソッドです。

このメソッドの引数fromInterfaceOrientationは回転する前の向きなので、回転後の向きの取得にinterfaceOrientationプロパティを使用します。

トランジションアニメーション(2)』で説明しましたが、beginAnimations:context:、commitAnimationsメソッドはiOS 4で非推奨となっているので、transitionWithView:duration:options:animations:completion:メソッドに置換する必要があるのですが、現在のシミュレーション環境ではアニメーションブロックの有無で視覚的差異が確認できず、またApress社のサイト内にサンプルコードでは使用していないため不要かもしれません。

そして条件分岐でポートレート/ランドスケープ時におけるボタンのレイアウトを指定しています。

ポートレート時の座標はInterface Builderで設定している内容と同じものです。

CGRectMakeでボタンの原点座標とサイズを指定し、frameプロパティで再配置用の座標とサイズとして設定します。
(frameプロパティの詳細は『スライドショーの簡易アニメーション(2)』を参照してください)

ランドスケープ時はボタンを3列2行に設定しています。

720


・willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
(UIViewControllerクラス)

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration

ユーザインターフェイスが回転する際の後半の前にビューコントローラに送信します。

このメソッドはデフォルトの実装では何もしません。

アニメーションの構成を一工程で済ませたい場合は、代わりにwillAnimateRotationToInterfaceOrientation:duration:メソッドをオーバーライドして使用してください。

アニメーションブロック内からこのメソッドが呼び出された場合、ヘッダとフッタがビューの元の位置に戻り、ビューの回転とスライドを完了するために使用されます。

このメソッドをオーバーライドすることによって、ビューの回転の後半の期間にアニメーションの構成を追加することができます。

例えば、コンテンツのズームレベルの調整やスクロール位置の変更、またはビューの他のアニメーションプロパティの修正に使用することができます。

このメソッドが呼び出される時、interfaceOrientationプロパティは新しい向きに設定されます。

fromInterfaceOrientation:回転する前のアプリケーションのユーザインターフェイスの向きの状態を指定します。
有効な値はUIInterfaceOrientationで説明します。
(UIInterfaceOrientationについては『Button Fun』を参照してください)

duration:回転を保留する後半の継続時間を秒単位で指定します。


・interfaceOrientation
(UIViewControllerクラス)

@property(nonatomic, readonly) UIInterfaceOrientation interfaceOrientation

インターフェイスの現在の向きを示します(読み込み専用)

有効な値はUIInterfaceOrientationで説明します。


・CGRectMake
(CGGeometry)

CGRect CGRectMake (
    CGFloat x,
    CGFloat y,
    CGFloat width,
    CGFloat height
);

指定した値で矩形の座標とサイズを返します。

x:矩形の原点となるx座標を指定します。

y:矩形の原点となるy座標を指定します。

width:矩形の幅を指定します。

height:矩形の高さを指定します。


●コードの修正

willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:メソッドの説明にもありますが、回転の前半の開始時に用いるwillAnimateFirstHalfOfRotationToInterfaceOrientation:duration:メソッドと合わせて一つとして扱うwillAnimateRotationToInterfaceOrientation:duration:メソッドに置き換えてみます。
(willAnimateRotationToInterfaceOrientation:duration:メソッドはiOS 3.0以降で使用できることから、Apress社のサイト内にサンプルコードでもOSのバージョンで条件分岐して使用する形になっています)

そして前述の通り(現行の開発環境ですと)視覚的効果が無さそうなのと、サンプルコードにも記述が無いので、アニメーションブロックの記述は削除します。

また、ランドスケープモード時のレイアウトが、

135
246

となっていますが、なんとなく違和感があるので

123
456

とします。

shouldAutorotateToInterfaceOrientation:メソッドも読み易いように、上下逆のポートレートの否定に条件を修正します。

また旧版の本書内では記述が抜けていますが、viewDidUnloadメソッドにアウトレットの所有権放棄を追加します。
(サンプルコードではviewDidUnloadメソッドにアウトレットの所有権放棄の記述があるものの、deallocでの解放の記述が抜けています)

コメントアウトしているメソッドを削除したAutosizeViewController.mの修正版は下記のようになります。
(太字が追加・修正した部分)

#import "AutosizeViewController.h"

@implementation AutosizeViewController

@synthesize button1;
@synthesize button2;
@synthesize button3;
@synthesize button4;
@synthesize button5;
@synthesize button6;

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
        duration:(NSTimeInterval)duration {

    if (interfaceOrientation == UIInterfaceOrientationPortrait ||
        interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
        button1.frame = CGRectMake( 20, 20, 125, 125);
        button2.frame = CGRectMake(175, 20, 125, 125);
        button3.frame = CGRectMake( 20, 168, 125, 125);
        button4.frame = CGRectMake(175, 168, 125, 125);
        button5.frame = CGRectMake( 20, 315, 125, 125);
        button6.frame = CGRectMake(175, 315, 125, 125);
    }
    else {
        button1.frame = CGRectMake( 20, 20, 125, 125);
        button2.frame = CGRectMake(177, 20, 125, 125);
        button3.frame = CGRectMake(328, 20, 125, 125);
        button4.frame = CGRectMake( 20, 155, 125, 125);
        button5.frame = CGRectMake(177, 155, 125, 125);
        button6.frame = CGRectMake(328, 155, 125, 125);
    }
}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.button1 = nil;
    self.button2 = nil;
    self.button3 = nil;
    self.button4 = nil;
    self.button5 = nil;
    self.button6 = nil;
    [super viewDidUnload];
}

- (void)dealloc {
    [button1 release];
    [button2 release];
    [button3 release];
    [button4 release];
    [button5 release];
    [button6 release];
    [super dealloc];
}

@end

722

実行結果は下図のようになります。

723

・willAnimateRotationToInterfaceOrientation:duration:
(UIViewControllerクラス)

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration

インターフェイスの回転を一工程で実行する前に、ビューコントローラに送信します。

このメソッドはデフォルトの実装では何もしません。

このメソッドをオーバーライドする場合は、willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:またはwillAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:メソッドをオーバーライドしないでください。

このメソッドはビューを回転するために、アニメーションブロック内から呼び出されます。

このメソッドをオーバーライドすることによって、ビューの回転の期間にアニメーションの構成を追加することができます。

例えば、コンテンツのズームレベルの調整やスクロール位置の変更、またはビューの他のアニメーションプロパティの修正に使用することができます。

:ビューにスライドして出入りするヘッダとフッタのアニメーションの実行は、アニメーションブロックとは別に実行されます。

このメソッドが呼び出される時、interfaceOrientationプロパティは既に新しい向きに設定されます。

従って、このメソッド内でビューにレイアウトの追加要求を実行することができます。

interfaceOrientation:ユーザインターフェイスの新しい向きを指定します。
有効な値はUIInterfaceOrientationで説明します。

duration:回転を保留する継続時間を秒単位で指定します。



参考文献

UIViewController Class Reference

CGGeometry Reference

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る






SoundLink Mini Bluetooth speaker_ii_limited
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
05 | 2017/06 | 07
Sun Mon Tue Wed Thu Fri Sat
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

SoundLink Mini Bluetooth speaker_ii_limited
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR