レイヤー ジオメトリ
ジオメトリに詳しくない人はここに来ないでください - プラトンのアカデミーへの入り口のサインです
第 2 章では、レイヤーの背後にある画像と、レイヤー座標と回転属性のいくつかのコントロールを紹介しました。この章では、レイヤーが親レイヤーと兄弟レイヤーに基づいて位置とサイズを内部的に制御する方法を見ていきます。また、レイヤー ジオメトリを管理する方法と、それが AutoResize と AutoLayout によってどのように影響を受けるかについても説明します。
UIView には、フレーム、境界、中心という 3 つの重要なレイアウト属性があり、それに応じて CALayer はフレーム、境界、位置と呼ばれます。明確にするために、「位置」はレイヤーに使用され、「中心」はビューに使用されますが、どちらも同じ値を表します。
フレームはレイヤーの外部座標 (つまり、親レイヤー上で占有されるスペース) を表し、境界は内部座標 ({0, 0} は通常レイヤーの左上隅です)、中心と位置は両方とも表します親レイヤーのanchorPointの位置に相対します。 anchorPoint のプロパティは後で紹介しますが、ここではレイヤーの中心点として考えてください。図 3.1 は、これらのプロパティが互いにどのように依存するかを示しています。
図 3.1 UIView と CALayer の座標系
ビューのフレーム、境界、中心プロパティは、ビューのフレームを操作するとき、実際にはビューの下の CALayer のフレームを変更するだけのメソッドです。レイヤーの外側のビューのフレームを変更することから独立させることはできません。
ビューやレイヤーの場合、フレームはあまり明確な属性ではありません。実際には、境界、位置、変換に基づいて計算される仮想属性であるため、いずれかの値が変更されると、フレームも変更されます。逆に、フレームの値を変更すると、その値にも影響します
回転や拡大縮小などのレイヤー上で変換を実行するとき、フレームは実際には軸に沿った長方形の領域全体を表すことに注意してくださいつまり、フレームの幅と高さが境界の幅と高さと一致しなくなります (図 3.2)
図 3.2 ビューまたはレイヤーを回転した後のフレーム属性
前に述べたように、ビューのレイヤーの center 属性とposition 属性は両方とも、親レイヤーを基準としたアンカーポイントの位置を指定します。レイヤーのアンカーポイントは、位置を通じてフレームの位置を制御します。アンカーポイントは、レイヤーを移動するために使用されるハンドルと考えることができます。
デフォルトでは、anchorPoint はレイヤーの中点に位置するため、レイヤーはこの点を中心に中心に配置されます。 anchorPoint プロパティは UIView インターフェイスによって公開されないため、ビューの位置プロパティは「center」と呼ばれます。ただし、レイヤーのアンカーポイントを移動することはできます。たとえば、レイヤーフレームの左上隅に配置すると、レイヤーのコンテンツは右下隅の位置方向に移動します (図 3.3)。中心にあるということ。
図 3.3 anchorPoint の変更による効果
第 2 章で説明した contentRect プロパティと contentCenter プロパティと同様に、anchorPoint はレイヤーの相対座標である単位座標で記述されます。レイヤーの左上隅は { です。 0, 0} 、右下隅は {1, 1} であるため、デフォルトの座標は {0.5, 0.5} です。 0 未満または 1 より大きい x 値と y 値を指定することで、anchorPoint をレイヤー範囲の外側に配置できます。
図 3.3 では、anchorPoint が変更されると、position プロパティは固定されたままで変化しませんが、フレームは移動することに注意してください。
それでは、anchorPoint を変更する必要があるのはいつでしょうか?レイヤーの位置は自由に変更できるので、anchorPointを変更すると混乱が生じないでしょうか?これを説明するために、実際の例を取り上げて、目覚まし時計をシミュレートするプロジェクトを作成してみましょう。
時計の文字盤と時計は 4 つの画像で構成されています (図 3.4)。簡単に説明すると、4 つの UIImageView インスタンスを使用して画像をロードおよびロードする従来の方法を引き続き使用します (もちろん、通常のビューを使用して画像を設定することもできます)。レイヤーの内容イメージ)。
図 3.4 時計の文字盤と時計を構成する 4 つの画像
目覚まし時計のコンポーネントは、IB (図 3.5) によってコンテナ ビュー内にネストされ、自動調整および自動レイアウトによって配置されます。は無効になっています。これは、自動調整がビューのフレームに影響を与えるためであり、図 3.2 のデモンストレーションによれば、ビューを回転するとフレームが変化し、レイアウトの一部の失敗が発生するためです。
NSTimer を使用して目覚まし時計を更新し、ビューのtransformプロパティを使用して時計を回転させます(このプロパティに詳しくない場合でも、心配しないでください。第5章「変換」で詳しく説明します) )、具体的なコードをリスト 3.1 に示します。
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 31 32 33 34 35 36 37 38 39 |
@interface ViewController ()
@property (非アトミック、弱い) IBOutlet UIImageView *hourHand; @property (非アトミック、弱い) IBOutlet UIImageView *minutHand; @property (非アトミック、弱い) IBOutlet UIImageView * SecondHand; @property (非アトミック、弱い) NSTimer *タイマー;
@end
@implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; //タイマーを開始します self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(tick) userInfo:nil repeats:YES]; ? //初期の手の位置を設定します [セルフティック]; }
- (void)tick { //時間を時、分、秒に変換します NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSグレゴリオ暦カレンダー]; NSUInteger units = NSHourCalendarUnit | NS分カレンダー単位 | NSSecondCalendarUnit; NSDateComponents *components = [カレンダーコンポーネント:単位fromDate:[NSDate date]]; CGFloat hoursAngle = (components.hour / 12.0) * M_PI * 2.0; //時針の角度を計算する // 分針の角度を計算する CGFloat minsAngle = (components. minutes / 60.0) * M_PI * 2.0; //秒針の角度を計算します CGFloat secsAngle = (components.秒 / 60.0) * M_PI * 2.0; //手を回転させます self.hourHand.transform = CGAffineTransformMakeRotation(hoursAngle); self.minutHand.transform = CGAffineTransformMakeRotation(minsAngle); self.secondHand.transform = CGAffineTransformMakeRotation(secsAngle); }
@end |
衹目,看起来有点奇怪(図3.6),因钟表的图片中心を中心に回転しますが、これは私たちが期待していた支点ではありません。
図 3.6 钟面、および不齐の钟指针
你も会は、Interface Builder 内で针図の位置を調整できると認めていますが、結果が見つからないため目的に到達できません钟面中の藴、同样同样同样正确能的正确的。。也许在末尾添加添加一个透明空间也是个个解决方案anchorPoint プロパティを使用して、-viewDidLoad メソッドに実行コードを追加して、各アンカーポイントの anchorPoint をいくつかのレベルに移動しました (クリア 3.2)。図 3.7 に正しい結果が示されています。
1
2
3
5 6 7 8 9 10 11 12
- (void)viewDidLoad { [スーパービューDidLoad]; | // アンカーポイントを調整します
self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f); self.minutHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f); self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
// タイマーを開始します }
| 図3.7钟面,和正确对齐の钟指针