如何添加跨越两个视图的渐变?

时间:2017-08-31 18:25:16

标签: ios objective-c uiview calayer cagradientlayer

我知道怎么做(1)但我该怎么做(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];

enter image description here

2 个答案:

答案 0 :(得分:2)

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

  1. 创建名为UIView的{​​{1}}子类来管理渐变图层。这很有用,因为这意味着您可以使用普通的UIKit技术来管理渐变布局(自动布局约束,自动调整蒙版,UIKit动画)。

  2. 对于应参与常用渐变的每个视图,添加GradientView子视图。同样设置每个GradientView的颜色,位置以及起点和终点。

  3. 对于应参与常用渐变的每个视图,请启用GradientView

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

  5. 通过这种方法,自动布局可以使渐变覆盖所有视图,即使它们改变了大小或移动。例如,当用户旋转设备时,您不必做任何特殊的操作来使渐变效果很好。

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

    unclipped

    在上面的视图调试器屏幕截图中,我禁用了剪辑。您可以看到两个渐变视图具有相同的渐变并共享相同的屏幕空间。 GradientViewtopGradient的子视图,topViewbottomGradient的子视图。

    如果我们打开裁剪,你只会看到bottomView的部分符合topGradient的界限,你只会看到topView的部分适合在bottomGradient的范围内。以下是启用剪辑的情况:

    clipped

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

    screen shot

    以下是bottomView的源代码:

    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
    

    以下是我如何创建使- (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

    - (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所需的最小空间。

答案 1 :(得分:1)

您可以通过使用渐变在视图顶部添加视图,然后通过从topView制作蒙版来剪切图形,然后将其添加到顶部的视图(让&#39 ; s称之为 let yourPath: UIBezierPath = //create the desired bezier path for your shapes let mask = CAShapeLayer() mask.path = yourPath.cgPath topView.layer.mask = mask ):

html_entity_decode