iphone - CAGradientLayer,无法很好地调整大小,旋转时撕裂

标签 iphone ios objective-c uiviewcontroller cagradientlayer

我正在尝试获取我的 CAGradientLayers,我用它来创建漂亮的渐变背景,以便在旋转和模态视图呈现时很好地调整大小,但它们不会发挥作用。

这是我刚刚创建的视频,显示了我的问题:注意旋转时的撕裂。

另请注意,该视频是通过在 OS X 上拍摄 iPhone 模拟器而创建的。我放慢了视频中的动画以突出显示我的问题。

Video of Problem...

这是我刚刚创建的 Xcode 项目(这是视频中显示的应用程序的源代码),基本上如图所示,问题发生在旋转时,尤其是在以模态方式呈现 View 时:

Xcode Project, modally presenting views with CAGradientLayer backgrounds...

对于它的值(value),我理解使用:

    [[self view] setBackgroundColor:[UIColor blackColor]];

在使过渡更加无缝和不那么刺耳方面做了合理的工作,但是如果您在当前处于横向模式时观看视频,以模态方式呈现 View ,您就会明白为什么上面的代码没有帮助.

有什么想法可以解决这个问题吗?

约翰

最佳答案

当您创建图层(例如渐变图层)时,没有 View 管理该图层(即使您将其添加为某些 View 图层的子图层)。像这样的独立层不参与 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

这就是在模拟器中启用慢动作的情况下的样子:

bad rotation

幸运的是,这是一个很容易解决的问题。您需要使渐变层由 View 管理。您可以通过创建一个使用 CAGradientLayer 作为其图层的 UIView 子类来实现此目的。代码很小:

// 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。由于您现在使用的是 View 而不是图层,因此您可以设置自动调整大小蒙版以将渐变大小保持为其 super View ,因此您以后无需执行任何操作即可处理旋转:

@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

结果如下:

good rotation

关于iphone - CAGradientLayer,无法很好地调整大小,旋转时撕裂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43050606/

相关文章:

ios - 无效的 Swift 支持——文件 libswiftCore.dylib 没有正确的代码签名

objective-c - 如何在 OSX 上自动关闭 NSAlert?

iphone - objective c type cast an object based on an NSString 类名

iOS 6 - ChatKit 私有(private) API - 发送短信

objective-c - NSTextView 中是否可以有 float 图像或文本框,或者我将使用什么来做到这一点?

javascript - 将 objective-c 变量传递给 ios 中的 javascript

ios - 如果在 LaunchScreen.storyboard 上使用该图像,图像在更改时不会更新

ios - 没有缺口的 iPhone X 模拟器截图

iphone - iphone os 框架本身会抛出 NSException 吗?

iphone - iOS 7 对文本应用字距调整和行距