CAGradientLayer、うまくサイズ変更されず、回転時に裂けてしまう 質問する

CAGradientLayer、うまくサイズ変更されず、回転時に裂けてしまう 質問する

美しいグラデーション背景を作成するために使用している 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

結果は次のとおりです。

良い回転

おすすめ記事