简体   繁体   English

UIView透明渐变

[英]UIView transparent gradient

Given an arbitrary UIView on iOS, is there a way using Core Graphics (CAGradientLayer comes to mind) to apply a "foreground-transparent" gradient to it? 给定iOS上的任意UIView,是否可以使用Core Graphics(想到CAGradientLayer)对其应用“前景透明”渐变?

I can't use a standard CAGradientLayer because the background is more complex than a UIColor. 我不能使用标准的CAGradientLayer,因为背景比UIColor更复杂。 I also can't overlay a PNG because the background will change as my subview is scrolled along its parent vertical scrollview (see image). 我也无法覆盖PNG,因为当子视图沿其父垂直滚动视图滚动时,背景将发生变化(参见图片)。

I have a non-elegant fallback: have my uiview clip its subviews and move a pre-rendered gradient png of the background as the parent scrollview is scrolled. 我有一个非优雅的回退:让我的uiview剪辑其子视图,并在滚动父滚动视图时移动背景的预渲染渐变png。

透明的uiview渐变问题

This was an embarrassingly easy fix: apply a CAGradientLayer as my subview's mask. 这是一个非常尴尬的简单修复:将CAGradientLayer用作子视图的蒙版。

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = _fileTypeScrollView.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor, nil];
gradientLayer.startPoint = CGPointMake(0.8f, 1.0f);
gradientLayer.endPoint = CGPointMake(1.0f, 1.0f);
_fileTypeScrollView.layer.mask = gradientLayer;

Thanks to Cocoanetics for pointing me in the right direction! 感谢Cocoanetics向我指出正确的方向!

This is how I'll do. 这就是我要做的。

Step 1 Define a custom gradient view (Swift 4): 步骤1定义自定义渐变视图(快速4):

import UIKit

class GradientView: UIView {
    override open class var layerClass: AnyClass {
        return CAGradientLayer.classForCoder()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let gradientLayer = self.layer as! CAGradientLayer
        gradientLayer.colors = [
            UIColor.white.cgColor,
            UIColor.init(white: 1, alpha: 0).cgColor
        ]
        backgroundColor = UIColor.clear
    }
}

Step 2 - Drag and drop a UIView in your storyboard and set its custom class to GradientView 第2步 -将UIView拖放到情节UIView中,并将其自定义类设置为GradientView

在此处输入图片说明

As an example, this is how the above gradient view looks like: 例如,上面的渐变视图如下所示:


https://github.com/yzhong52/GradientViewDemo https://github.com/yzhong52/GradientViewDemo

渐变示例

I just ran into the same issue and wound up writing my own class. 我只是遇到了同样的问题,最后写了自己的课。 It seems like serious overkill, but it was the only way I could find to do gradients with transparency. 这似乎严重过头了,但这是我发现透明化渐变的唯一方法。 You can see my writeup and code example here 您可以在这里看到我的文章和代码示例

It basically comes down to a custom UIView that creates two images. 基本上,它归结为创建两个图像的自定义UIView。 One is a solid color, the other is a gradient that is used as an image mask. 一种是纯色,另一种是用作图像蒙版的渐变。 From there I applied the resulting image to the uiview.layer.content. 从那里,我将生成的图像应用于uiview.layer.content。

I hope it helps, Joe 我希望能帮上忙,乔

I used the accepted (OP's) answer above and ran into the same issue noted in an upvoted comment - when the view scrolls, everything that started offscreen is now transparent, covered by the mask. 我使用了上面接受的(OP)答案,并遇到了同一问题, 问题已在经投票赞成的注释中显示 -当视图滚动时,屏幕外开始的所有内容现在都是透明的,被蒙版覆盖。

The solution was to add the gradient layer as the superview 's mask, not the scroll view 's mask. 解决方案是将渐变层添加为超级视图的蒙版,而不是滚动视图的蒙版。 In my case, I'm using a text view, which is contained inside a view called contentView . 就我而言,我使用的是文本视图,该视图包含在名为contentView的视图内。

I added a third color and used locations instead of startPoint and endPoint , so that items below the text view are still visible. 我添加了第三种颜色,并使用了locations而不是startPointendPoint ,以便文本视图下方的项目仍然可见。

let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.contentView!.bounds
gradientLayer.colors = [UIColor.white.cgColor, UIColor.clear.cgColor, UIColor.white.cgColor]

// choose position for gradient, aligned to bottom of text view
let bottomOffset = (self.textView!.frame.size.height + self.textView!.frame.origin.y + 5)/self.contentView!.bounds.size.height
let topOffset = bottomOffset - 0.1
let bottomCoordinate = NSNumber(value: Double(bottomOffset))
let topCoordinate = NSNumber(value: Double(topOffset))
gradientLayer.locations = [topCoordinate, bottomCoordinate, bottomCoordinate]

self.contentView!.layer.mask = gradientLayer

Before, the text that started offscreen was permanently invisible. 以前,屏幕外开始的文本是永久不可见的。 With my modifications, scrolling works as expected, and the "Close" button is not covered by the mask. 经过我的修改,滚动按预期进行,并且“关闭”按钮未被遮罩覆盖。

屏幕截图

I hate to say it, but I think that you are into the CUSTOM UIView land. 我不想这么说,但是我认为您已经进入CUSTOM UIView领域。 I think that I would try to implement this in a custom UIView overiding the drawRect routine. 我认为我会尝试在覆盖drawRect例程的自定义UIView中实现此功能。

With this, you could have that view, place on top of your actual scrollview, and have your gradient view (if you will) "pass-on" all touch events (ie relinquish first responder). 这样,您就可以拥有该视图,将其放置在实际的滚动视图之上,并让您的渐变视图(如果可以)“传递”所有触摸事件(即放弃第一响应者)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM