CALayerコンテンツの指定
レイヤ内のコンテンツの位置決め
Cocoaビューを使って何かを表示するときには、NSViewをサブクラス化し、drawRect:を実装する必要があります。しかし多くの場合は、サブクラスを作成する必要はなく、CALayerインスタンスを直接使うことができます。CALayerはキー値コーディングに準拠したコンテナです。つまり、サブクラス化せずにインスタンスに任意の値を格納でき、これにより多くの場合サブクラス化を避けることができます。
CALayerインスタンスのコンテンツは、次のいずれかの方法で指定します。
コンテンツイメージを含んでいるCGImageRefを使って、レイヤインスタンスのcontentsプロパティを明示的に設定する。
コンテンツを提供、つまり描画するデリゲートを指定する。
CALayerをサブクラス化し、表示メソッドの1つをオーバーライドする。
レイヤのコンテンツイメージは、CGImageRefへのcontentsプロパティによって指定されます。これは、レイヤの作成時(レイヤのコンテンツプロパティの設定参照)やそれ以外の場合に別のオブジェクトから行うことができます。
リスト 4 レイヤのコンテンツプロパティの設定
CALayer *theLayer; |
// レイヤを作成し、境界矩形と位置を作成する |
theLayer=[CALayer layer]; |
theLayer.position=CGPointMake(50.0f,50.0f) |
theLayer.bounds=CGRectMake(0.0f,0.0f,100.0f,100.0f); |
// コンテンツプロパティを、theImage(別の場所でロードされている) |
// によって指定されたCGImageRefに設定する。 |
theLayer.contents=theImage; |
displayLayer:メソッドまたはdrawLayer:inContext:メソッドを実装するデリゲートクラスを作成し、レイヤコンテンツイメージを設定することで、レイヤのコンテンツの描画や、より優れたカプレセル化を行うことができます。
displayLayer:メソッドを実装するデリゲートは、指定されたレイヤに対してどのイメージが表示されるべきかを決定し、それに応じてレイヤのcontentsプロパティを設定できます。displayLayer:の実装例に示すdisplayLayer:の実装例では、stateキーの値に応じてtheLayerのcontentsプロパティを設定しています。CALayerインスタンスがキー値コーディングコンテナとして機能するため、state値を格納するためにサブクラス化する必要はありません。
リスト 5 デリゲートメソッドdisplayLayer:の実装例
- (void)displayLayer:(CALayer *)theLayer |
{ |
// レイヤのstateキーの値をチェック |
if ([[theLayer valueForKey:@"state"] boolValue]) |
{ |
// yesのイメージを表示 |
theLayer.contents=[someHelperObject loadStateYesImage]; |
} |
else { |
// noのイメージを表示 |
theLayer.contents=[someHelperObject loadStateNoImage]; |
} |
} |
レイヤのコンテンツをイメージからロードせずに描画する場合は、drawLayer:inContext:デリゲートメソッドを実装します。デリゲートには、コンテンツを必要としているレイヤと、コンテンツの描画先となるCGContextRefが渡されます。
デリゲートメソッドdrawLayer:inContext:の実装例に示すdrawLayer:inContext::の実装例では、theLayerによって返されたlineWidthキーとlineColorキーの値を描画します。
リスト 6 デリゲートメソッドdrawLayer:inContext:の実装例
- (void)drawLayer:(CALayer *)theLayer |
inContext:(CGContextRef)theContext |
{ |
CGMutablePathRef thePath = CGPathCreateMutable(); |
CGPathMoveToPoint(thePath,NULL,15.0f,15.f); |
CGPathAddCurveToPoint(thePath, |
NULL, |
15.f,250.0f, |
295.0f,250.0f, |
295.0f,15.0f); |
CGContextBeginPath(theContext); |
CGContextAddPath(theContext, thePath ); |
CGContextSetLineWidth(theContext, |
[theLayer valueForKey:@"lineWidth"]); |
CGContextSetStrokeColorWithColor(theContext, |
[theLayer valueForKey:@"lineColor"]); |
CGContextStrokePath(theContext); |
// パスを解放 |
CFRelease(thePath); |
} |
多くの場合は不要ですが、CALayerをサブクラス化し、描画メソッドと表示メソッドを直接オーバーライドすることができます。これは通常、デリゲートを通じては提供できないようなカスタムの動作がレイヤに要求される場合に行います。
サブクラス化により、CALayer表示メソッドをオーバーライドし、レイヤのコンテンツに適切なイメージを設定できます。CALayer表示メソッドのオーバーライドの例に示す例は、デリゲートメソッドdisplayLayer:の実装例に示したdisplayLayer:のデリゲートの実装と同じ機能を提供します。違いは、サブクラスではCALayerのキー値コーディングコンテナ機能に依存するのではなく、stateをインスタンスプロパティとして定義する点です。
リスト 7 CALayer表示メソッドのオーバーライドの例
- (void)display |
{ |
// レイヤのstateキーの値をチェック |
if (self.state) |
{ |
// yesのイメージを表示 |
self.contents=[someHelperObject loadStateYesImage]; |
} |
else { |
// noのイメージを表示 |
self.contents=[someHelperObject loadStateNoImage]; |
} |
} |
CALayerサブクラスは、drawInContext:をオーバーライドすることにより、レイヤのコンテンツをグラフィックスコンテキストに描画できます。CALayer drawInContext:メソッドのオーバーライドの例に示す例では、デリゲートメソッドdrawLayer:inContext:の実装例に示したデリゲートの実装と同じコンテンツイメージを生成します。この場合も、実装の唯一の違いはサブクラスのインスタンスプロパティとして、lineWidthとlineColorが宣言される点です。
リスト 8 CALayer drawInContext:メソッドのオーバーライドの例
- (void)drawInContext:(CGContextRef)theContext |
{ |
CGMutablePathRef thePath = CGPathCreateMutable(); |
CGPathMoveToPoint(thePath,NULL,15.0f,15.f); |
CGPathAddCurveToPoint(thePath, |
NULL, |
15.f,250.0f, |
295.0f,250.0f, |
295.0f,15.0f); |
CGContextBeginPath(theContext); |
CGContextAddPath(theContext, thePath ); |
CGContextSetLineWidth(theContext, |
self.lineWidth); |
CGContextSetStrokeColorWithColor(theContext, |
self.lineColor); |
CGContextStrokePath(theContext); |
CFRelease(thePath); |
} |
CALayerのプロパティcontentsGravityにより、レイヤの境界内におけるレイヤのcontentsイメージの位置と縮尺を指定できます。デフォルトでは、コンテンツイメージはレイヤの境界矩形全体に塗りつぶされ、そのイメージに適したアスペクト比は無視されます。
contentsGravity位置決め定数を使って、イメージをレイヤの端に沿って配置するか、レイヤの角に合わせて配置するか、レイヤの境界矩形内の中心に配置するかを指定できます。レイヤのcontentsGravityプロパティに対する位置決め定数に、位置決め定数とそれに対応する位置の一覧を示します。
位置決め定数 | 説明 |
|---|---|
| コンテンツイメージをレイヤの左上角に配置します。 |
| コンテンツイメージを、レイヤの上端に沿って水平方向の中央に配置します。 |
| コンテンツイメージをレイヤの右上角に配置します。 |
| コンテンツイメージを、レイヤの左端に沿って垂直方向の中央に配置します。 |
| コンテンツイメージをレイヤの中央に配置します。 |
| コンテンツイメージを、レイヤの右端に沿って垂直方向の中央に配置します。 |
| コンテンツイメージをレイヤの左下角に配置します。 |
| コンテンツイメージを、レイヤの下端に沿って中央に配置します。 |
| コンテンツイメージをレイヤの右下角に配置します。 |
「レイヤのcontentsGravityプロパティの位置決め定数」に、サポートされているコンテンツ位置とそれに対応する定数を示します。
contentsGravityプロパティをレイヤのcontentsGravityプロパティの拡大縮小定数に示す定数の1つに設定することによって、コンテンツイメージを拡大縮小できます。
拡大縮小定数 | 説明 |
|---|---|
| コンテンツイメージを、レイヤの境界矩形全体を完全に塗りつぶすようにサイズ変更します。コンテンツに適したアスペクト比は無視される可能性があります。これはデフォルトで適用されます。 |
| コンテンツイメージを、アスペクト比を維持しながらレイヤの境界矩形内にできるだけ大きなサイズで表示されるように拡大縮小します。 |
「レイヤのcontentsGravityプロパティに対する拡大縮小定数」は、サイズ変更モードを使うことによって、正方形のイメージが矩形のレイヤの境界内にどのように埋められるかを示しています。
Last updated: 2007-12-06