如何添加跨两个视图的渐变? [英] How can I add a gradient that spans two views?

查看:92
本文介绍了如何添加跨两个视图的渐变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道该怎么做(1),但是我该怎么做(2)?

I know how to do (1) but how can I do (2)?

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
CAGradientLayer *gradient = [CAGradientLayer layer];

gradient.frame = view.bounds;
gradient.colors = @[(id)[UIColor blueColor].CGColor, (id)[UIColor redColor].CGColor];

[view.layer insertSublayer:gradient atIndex:0];

推荐答案

有几种方法可以做到这一点.这是一种方法:

There are several ways you could do this. Here's one way:

  1. 创建一个名为GradientViewUIView子类来管理渐变层.这很有用,因为这意味着您可以使用常规的UIKit技术来管理渐变布局(自动布局约束,自动调整蒙版大小,UIKit动画).

  1. Create a UIView subclass named GradientView to manage the gradient layer. This is helpful because it means you can use the normal UIKit techniques to manage the gradient layout (auto layout constraints, autoresizing masks, UIKit animations).

对于应参与公共渐变的每个视图,添加一个GradientView子视图.分别设置每个GradientView的颜色,位置以及起点和终点.

For each view that should participate in the common gradient, add a GradientView subview. Set up each GradientView's colors, locations, and start and end points identically.

对于应参与公共渐变的每个视图,请打开clipsToBounds.

For each view that should participate in the common gradient, turn on clipsToBounds.

使用自动布局约束使每个GradientView跨越所有参与的超级视图. (了解约束可以跨越超级视图/子视图边界很重要).

Use auto layout constraints to make each GradientView span all of the participating superviews. (It's important to understand that constraints can cross superview/subview boundaries).

使用这种方法,自动布局可以使渐变覆盖所有视图,即使它们改变大小或移动也是如此.例如,当用户旋转设备时,您无需执行任何特殊操作即可使渐变呈现出良好的动画效果.

With this approach, auto layout takes care of making the gradient cover all of the views even if they change size or move around. For example, you won't have to do anything special to make the gradients animate nicely when the user rotates the device.

因此,对于您的两视图示例,我建议您建立这样的视图层次结构:

Thus, for your two-view example, I'm proposing that you set up a view hierarchy like this:

在上面的视图调试器屏幕快照中,我禁用了裁剪.您可以看到两个渐变视图具有相同的渐变并共享相同的屏幕空间. topGradienttopView的子视图,bottomGradientbottomView的子视图.

In the view debugger screenshot above, I disabled clipping. You can see that the two gradient views have identical gradients and share the same screen space. The topGradient is a subview of topView and bottomGradient is a subview of bottomView.

如果我们打开剪辑,您只会看到topGradient的一部分适合topView的边界,而您只会看到bottomGradient的一部分适合bottomView的边界.界限.启用裁剪后的样子如下:

If we turn clipping on, you'll only see the part of topGradient that fits inside topView's bounds, and you'll only see the part of bottomGradient that fits inside bottomView's bounds. Here's what it looks like with clipping enabled:

这是我在模拟器中测试程序的屏幕截图:

And here's a screen shot of my test program in the simulator:

这是GradientView的源代码:

@interface GradientView: UIView
@property (nonatomic, strong, readonly) CAGradientLayer *gradientLayer;
@end

@implementation GradientView
+ (Class)layerClass { return CAGradientLayer.class; }
- (CAGradientLayer *)gradientLayer { return (CAGradientLayer *)self.layer; }
@end

这是我用来创建所有视图的代码:

Here's the code I used to create all of the views:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *topView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 50)];
    topView.layer.cornerRadius = 10;
    topView.clipsToBounds = YES;
    UIView *topGradient = [self newGradientView];
    [topView addSubview:topGradient];
    [self.view addSubview:topView];

    UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(20, 90, 100, 50)];
    bottomView.layer.cornerRadius = 10;
    bottomView.clipsToBounds = YES;
    UIView *bottomGradient = [self newGradientView];
    [bottomView addSubview:bottomGradient];
    [self.view addSubview:bottomView];

    [self constrainView:topGradient toCoverViews:@[topView, bottomView]];
    [self constrainView:bottomGradient toCoverViews:@[topView, bottomView]];
}

- (GradientView *)newGradientView {
    GradientView *gv = [[GradientView alloc] initWithFrame:CGRectZero];
    gv.translatesAutoresizingMaskIntoConstraints = NO;
    gv.gradientLayer.colors = @[(__bridge id)UIColor.blueColor.CGColor, (__bridge id)UIColor.redColor.CGColor];
    return gv;
}

这是我如何创建使GradientView(或任何视图)覆盖一组视图的约束的方法:

And here's how I create the constraints that make a GradientView (or any view) cover a set of views:

- (void)constrainView:(UIView *)coverer toCoverViews:(NSArray<UIView *> *)coverees {
    for (UIView *coveree in coverees) {
        NSArray<NSLayoutConstraint *> *cs;

        cs = @[
               [coverer.leftAnchor constraintLessThanOrEqualToAnchor:coveree.leftAnchor],
               [coverer.rightAnchor constraintGreaterThanOrEqualToAnchor:coveree.rightAnchor],
               [coverer.topAnchor constraintLessThanOrEqualToAnchor:coveree.topAnchor],
               [coverer.bottomAnchor constraintGreaterThanOrEqualToAnchor:coveree.bottomAnchor]];
        [NSLayoutConstraint activateConstraints:cs];

        cs = @[
               [coverer.leftAnchor constraintEqualToAnchor:coveree.leftAnchor],
               [coverer.rightAnchor constraintEqualToAnchor:coveree.rightAnchor],
               [coverer.topAnchor constraintEqualToAnchor:coveree.topAnchor],
               [coverer.bottomAnchor constraintEqualToAnchor:coveree.bottomAnchor]];
        for (NSLayoutConstraint *c in cs) { c.priority = UILayoutPriorityDefaultHigh; }
        [NSLayoutConstraint activateConstraints:cs];
    }
}

greaterThanOrEqual/lessThanOrEqual约束(默认情况下具有优先级)必须确保coverer覆盖每个coveree的整个框架.优先级较低的equal约束将确保coverer占用覆盖每个coveree所需的最小空间.

The greaterThanOrEqual/lessThanOrEqual constraints, which (by default) have required priority, ensure that coverer covers the entire frame of each coveree. The equal constraints, which have lower priority, then ensure that coverer occupies the minimum space required to cover each coveree.

这篇关于如何添加跨两个视图的渐变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆