美しいグラデーション背景を作成するために使用している CAGradientLayers を、回転やモーダル ビューの表示時に適切にサイズ変更できるようにしようとしていますが、うまくいきません。
これは私が作成した、問題を示すビデオです。回転時にティアリングが発生することに注意してください。
また、このビデオは OS X 上の iPhone シミュレーターを撮影して作成されたことにも注意してください。問題を強調するために、ビデオ内のアニメーションを遅くしています。
以下は私が作成したばかりの Xcode プロジェクトです (ビデオで紹介されているアプリのソース)。基本的に、図に示すように、問題は回転時に発生し、特にビューがモーダルで表示されている場合に発生します。
Xcode プロジェクト、CAGradientLayer 背景を持つビューをモーダルで表示します...
私が理解している限りでは、以下を使用します:
[[self view] setBackgroundColor:[UIColor blackColor]];
遷移をよりシームレスにし、違和感を軽減するという点で、妥当な仕事をしていますが、現在ランドスケープ モードでモーダル ビューを表示しているビデオを見ると、上記のコードが役に立たない理由がわかります。
これを解決するために何ができるか、何かアイデアはありますか?
ジョン
ベストアンサー1
レイヤー (グラデーション レイヤーなど) を作成すると、そのレイヤーを管理するビューは存在しません (ビューのレイヤーのサブレイヤーとして追加した場合でも)。このようなスタンドアロン レイヤーは、UIView
アニメーション システムに参加しません。
したがって、グラデーション レイヤーのフレームを更新すると、レイヤーは独自のデフォルトのアニメーション パラメータを使用して変更をアニメーション化します。(これを「暗黙的なアニメーション」と呼びます)。これらのデフォルトのパラメータは、インターフェイスの回転に使用されるアニメーション パラメータと一致しないため、奇妙な結果になります。
あなたのプロジェクトは見ていませんが、このコードで問題を再現するのは簡単です:
@interface ViewController ()
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.gradientLayer = [CAGradientLayer layer];
self.gradientLayer.colors = @[ (__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor blackColor].CGColor ];
[self.view.layer addSublayer:self.gradientLayer];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.gradientLayer.frame = self.view.bounds;
}
@end
シミュレーターでスローモーションを有効にすると、次のようになります。
幸いなことに、この問題は簡単に解決できます。グラデーション レイヤーをビューで管理する必要があります。そのためには、UIView
をレイヤーとして使用するサブクラスを作成しますCAGradientLayer
。コードは非常に小さいです。
// GradientView.h
@interface GradientView : UIView
@property (nonatomic, strong, readonly) CAGradientLayer *layer;
@end
// GradientView.m
@implementation GradientView
@dynamic layer;
+ (Class)layerClass {
return [CAGradientLayer class];
}
@end
GradientView
次に、 の代わりにを使用するようにコードを変更する必要がありますCAGradientLayer
。レイヤーの代わりにビューを使用しているため、自動サイズ変更マスクを設定してグラデーションのサイズをスーパービューに合わせることができます。そのため、回転を処理するために後で何もする必要はありません。
@interface ViewController ()
@property (nonatomic, strong) GradientView *gradientView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.gradientView = [[GradientView alloc] initWithFrame:self.view.bounds];
self.gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.gradientView.layer.colors = @[ (__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor blackColor].CGColor ];
[self.view addSubview:self.gradientView];
}
@end
結果は次のとおりです。