如何在真实设备上的 iOS 10 中将渐变应用到 UIView

Posted

技术标签:

【中文标题】如何在真实设备上的 iOS 10 中将渐变应用到 UIView【英文标题】:How to apply Gradient to UIView in iOS 10 on a real device 【发布时间】:2017-01-16 16:34:30 【问题描述】:

我有这个扩展可以在 Swift 中为视图添加渐变:

extension UIView 
    func addGradientWithColor(colorTop: UIColor, colorButton: UIColor)
        let gradient = CAGradientLayer()
        gradient.frame = self.bounds
        gradient.colors = [colorTop.cgColor, colorButton.cgColor]

        self.layer.insertSublayer(gradient, at: 0)
    

然后,我在我的 UIViewController 中使用它:

override func viewDidLoad()
    self.view.addGradientWithColor(colorTop: UIColor.red, colorButton: UIColor.clear)        
    super.viewDidLoad()

我运行模拟器,它运行良好。但是当我想在真实设备上使用我的应用时,渐变不起作用。

PD:我尝试了很多方法来制作渐变,但在真实设备上都没有效果。

【问题讨论】:

可以看到一般的答案here 【参考方案1】:

问题是当视图的大小发生变化时您没有调整图层的大小,因此它保持在初始值,这主要取决于视图是如何创建的。

我建议使用UIView 子类,并在layoutSubviews 方法中更新图层大小,该方法总是在视图调整大小时被调用:

@IBDesignable
open class GradientView: UIView 
    @IBInspectable
    public var startColor: UIColor = .white 
        didSet 
            gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
            setNeedsDisplay()
        
    
    @IBInspectable
    public var endColor: UIColor = .white 
        didSet 
            gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
            setNeedsDisplay()
        
    

    private lazy var gradientLayer: CAGradientLayer = 
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = self.bounds
        gradientLayer.colors = [self.startColor.cgColor, self.endColor.cgColor]
        return gradientLayer
    ()

    override init(frame: CGRect) 
        super.init(frame: frame)
        layer.insertSublayer(gradientLayer, at: 0)
    

    public required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        layer.insertSublayer(gradientLayer, at: 0)
    

    open override func layoutSubviews() 
        super.layoutSubviews()
        gradientLayer.frame = bounds
    

上面的代码还可以让您从 Xcode 调整开始和结束颜色,以便您估计视图在部署时的外观。

【讨论】:

什么是ToTGradientView?谷歌搜索它只会出现这个 *** 帖子 其中一种颜色可以是.clear吗?说从黑色渐变到透明? 它有效。最后是我没有将渐变视图背景设置为不透明的问题。感谢您的帮助!【参考方案2】:

试试这个,它对我有用。代码:

let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame.size = self.gradientView.frame.size
gradientLayer.colors = [UIColor.white.cgColor,UIColor.red.withAlphaComponent(1).cgColor] //Use diffrent colors
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
self.gradientView.layer.addSublayer(gradientLayer)

更多详细解释见:Gradient On UIView

【讨论】:

【参考方案3】:

只需确保您使用的是color.cgColor 而不是color

【讨论】:

我在这个“细节”上花费的时间比我愿意承认的要多。【参考方案4】:

此代码用于 Swift 5 中具有透明背景的渐变。[透明|白色混合]

    let gradientLayer:CAGradientLayer = CAGradientLayer()
    gradientLayer.colors = [UIColor.white.withAlphaComponent(0.0).cgColor, UIColor.white.cgColor]
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
    gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
    gradientLayer.frame.size = self.gradientView.frame.size

    self.gradientView.layer.addSublayer(gradientLayer)

【讨论】:

【参考方案5】:

使用 @Cristik 和其他用户的答案(我找不到谁的答案,所以如果你是那个用户,请告诉我,以便我给你功劳)

我得到了这个(在情节提要/真实设备/模拟器中更新并允许垂直或水平):

在 Xcode 11、Swift 5 上测试:

@IBDesignable class GradientView: UIView 

    @IBInspectable
    public var firstColor: UIColor = .white 
        didSet 
            gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
            setNeedsDisplay()
        
    

    @IBInspectable
    public var secondColor: UIColor = .white 
        didSet 
            gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
            setNeedsDisplay()
        
    

    @IBInspectable var vertical: Bool = true 
        didSet 
            updateGradientDirection()
        
    

    lazy var gradientLayer: CAGradientLayer = 
        let layer = CAGradientLayer()
        layer.colors = [firstColor.cgColor, secondColor.cgColor]
        layer.startPoint = CGPoint.zero
        return layer
    ()

    // MARK: - Lifecycle

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        applyGradient()
    

    override init(frame: CGRect) 
        super.init(frame: frame)
        applyGradient()
    

    override func prepareForInterfaceBuilder() 
        super.prepareForInterfaceBuilder()
        applyGradient()
    

    override func layoutSubviews() 
        super.layoutSubviews()
        updateGradientFrame()
    

    // MARK: - Helper

    func applyGradient() 
        updateGradientDirection()
        layer.sublayers = [gradientLayer]
    

    func updateGradientFrame() 
        gradientLayer.frame = bounds
    

    func updateGradientDirection() 
        gradientLayer.endPoint = vertical ? CGPoint(x: 0, y: 1) : CGPoint(x: 1, y: 0)
    

【讨论】:

以上是关于如何在真实设备上的 iOS 10 中将渐变应用到 UIView的主要内容,如果未能解决你的问题,请参考以下文章

渐变不覆盖 iphone plus 设备上的图像 ios swift 3

如何在phonegap ios中将设备令牌从Xcode抓取到javascript?

Flutter 应用程序无法在真实的 iOS 设备上运行(白屏)

iOS安全区域无法在真实设备上运行

数据未从 iphone 传输到真实设备上的 iWatch (AppleWatch)

IOS 10 或 11 上的 Ionic 3 标头高度