【问题标题】:Draw gradient inside UIView draw() with swift使用 swift 在 UIView draw() 中绘制渐变
【发布时间】:2018-05-31 20:07:01
【问题描述】:

我想在所有视图中添加渐变背景。

我认为不需要在所有视图控制器中创建视图的 IBOutlet 的方式是从 UIView 创建一个新类,然后在 draw() 中将生成 CAGradientLayer 的代码放在查看。

因此,在界面构建器中,我只需选择背景视图并将其类设置为我的自定义类。到目前为止它有效。

我的问题是我是否可以毫无问题地做到这一点。有人知道好吗? 因为继承自 UIView 的模型文件带有注释: //只有在执行自定义绘图时才覆盖draw()。

而且我不知道创建图层是否重要。或者如果 draw() 只是低级绘图或类似的东西。对draw()函数的最佳用法一无所知。

这是代码:

override func draw(_ rect: CGRect) {

        let layer = CAGradientLayer()
        layer.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)

        let color1 = UIColor(red: 4/255, green: 39/255, blue: 105/255, alpha: 1)
        let color2 = UIColor(red: 1/255, green: 91/255, blue: 168/255, alpha: 1)

        layer.colors = [color1.cgColor, color2.cgColor]
        self.layer.addSublayer(layer)
    }

【问题讨论】:

  • 您需要渐变层的位置属性。

标签: ios swift uiview gradient


【解决方案1】:

您不应该在 draw 函数中添加 CAGradientLayer。

如果您想为视图添加渐变,那么最简单的方法是使用图层(就像您正在做的那样)但不是这样......

您应该将其作为 init 方法的一部分添加到您的视图中,然后在布局子视图方法中更新其框架。

这样的……

class MyView: UIView {
    let gradientLayer: CAGradientLayer = {
        let l = CAGradientLayer()
        let color1 = UIColor(red: 4/255, green: 39/255, blue: 105/255, alpha: 1)
        let color2 = UIColor(red: 1/255, green: 91/255, blue: 168/255, alpha: 1)
        l.colors = [color1.cgColor, color2.cgColor]
        return l
    }()

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

        layer.addSublayer(gradientLayer)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        gradientLayer.frame = bounds
    }
}

【讨论】:

  • 感谢您的回答。但是使用此代码,不会显示渐变。我只有一个白色背景(我的视图本身的颜色)。我需要在哪里调用 init(frame) ?我认为它永远不会被调用。 xcode 要求我放一个 init(coder),我可以在其中调用 init(frame) 吗?
  • 如果你想支持 IB/storyboards 那么你需要同时支持 init(frame:)init(coder:) - 我通常有一个名为 setup() 的函数被两个初始化器调用。跨度>
【解决方案2】:

我会创建 UIView 扩展并在需要时应用它。

extension UIView {
        func withGradienBackground(color1: UIColor, color2: UIColor, color3: UIColor, color4: UIColor) {
            let layerGradient = CAGradientLayer()

            layerGradient.colors = [color1.cgColor, color2.cgColor, color3.cgColor, color4.cgColor]
            layerGradient.frame = bounds
            layerGradient.startPoint = CGPoint(x: 1.5, y: 1.5)
            layerGradient.endPoint = CGPoint(x: 0.0, y: 0.0)
            layerGradient.locations = [0.0, 0.3, 0.4, 1.0]

            layer.insertSublayer(layerGradient, at: 0)
        }
}

您可以在此处更改 func 声明以指定 startPointendPointlocations 参数作为变量。

然后像这样调用这个方法

gradienView.withGradienBackground(color1: UIColor.green, color2: UIColor.red, color3: UIColor.blue, color4: UIColor.white)

附言 请注意,colors 数组中可以有任意多的颜色

【讨论】:

  • 但是有了这个扩展,我需要在所有视图控制器中创建一个视图的出口来调用渐变函数。我想避免这种情况。无论如何,谢谢。
【解决方案3】:

您可以使用@IBDesignable@IBInspectableStoryboard 配置startColor 和endColor 属性。如果要在 draw(_ rect:) 方法中绘制,请使用指定颜色和位置的 CGGradient 而不是 CAGradientLayer。 Simple Gradient 类和draw(_ rect: CGRect) 函数如下所示

import UIKit

@IBDesignable 
class GradientView: UIView {

    @IBInspectable var startColor: UIColor = UIColor(red: 4/255, green: 39/255, blue: 105/255, alpha: 1)
    @IBInspectable var endColor: UIColor = UIColor(red: 1/255, green: 91/255, blue: 168/255, alpha: 1)

    override func draw(_ rect: CGRect) {

      let context = UIGraphicsGetCurrentContext()!
      let colors = [startColor.cgColor, endColor.cgColor]

      let colorSpace = CGColorSpaceCreateDeviceRGB()

      let colorLocations: [CGFloat] = [0.0, 1.0]

      let gradient = CGGradient(colorsSpace: colorSpace,
                                     colors: colors as CFArray,
                                  locations: colorLocations)!

      let startPoint = CGPoint.zero
      let endPoint = CGPoint(x: 0, y: bounds.height)
      context.drawLinearGradient(gradient,
                          start: startPoint,
                            end: endPoint,
                        options: [CGGradientDrawingOptions(rawValue: 0)])
    }
}

您可以在heretutorial 阅读更多相关信息

【讨论】:

  • 谢谢。我认为这是我正在寻找的更近的地方。而且效果很好。
  • 使用 IBInspectable 和 IBDesignable 的好主意,让它变得完美。
  • @curiously77 更新了代码以修复崩溃。谢谢。
  • @curiously77 不确定这是因为 Swift 5。在 drawLinearGradient 方法中,选项被声明为 OptionSetType 类型的枚举。所以你在这里传递 CGGradientDrawingOptions 枚举类型或包含来自枚举的元素的集合。当我们不想应用任何选项时,我们指定空 []。详情请查看stackoverflow.com/questions/36323615/…此问题。
  • 另外我也分享了教程和文档链接,如果您有任何疑问,请查看。在 Playground 中试试上面的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-30
  • 2014-01-20
  • 1970-01-01
相关资源
最近更新 更多