ofelia
ofelia

Reputation: 17

How do i make uiview using linear gradient in swift

i have in my figma this style: background: linear-gradient(155.98deg, #F5FEFF 0%, #C5F8FF 0%, rgba(106, 164, 189, 0.5) 47.57%, #0E8B9C 88.75%), #FFFFFF; i need to make my uiview as linear-gradient

Upvotes: 0

Views: 4884

Answers (2)

Rob
Rob

Reputation: 437552

The basic idea is to configure a CAGradientLayer with an array of colors and locations. If you want a diagonal gradient, specify a startPoint and endPoint, too.

But you need to decipher that Figma CSS. The first parameter to linear-gradient is the angle. Linear gradients in iOS are not measured in angles, but rather with startPoint and endPoint, both of which are CGPoint references where 0, 0 represents the upper left corner of the view and 1, 1 represents the lower right corner. Your angle of 155.98deg suggests that you're looking for a “from upper left to lower right” gradient, which would be a startPoint of 0, 0 and an endPoint of 1, 1. (The exact mapping between the angle and these CGPoint values will vary based upon the aspect ratio of the view in question.)

The next parameter to linear-gradient is an array of tuples of colors and location. Solid colors are represented in hex strings. Translucent colors are represented with integer rgb values. So #F5FEFF 0% is at location 0.0 and a color of 0xf5 for red, 0xfe for green, and 0xff for blue. You need to divide all those numbers by 0xff (or 255). (The Xcode color literal will do that conversion for you.) And the 0% at the end of the string is the relative location of this color in the gradient (where 0% is the start of the gradient and 100% is the end). This correlates nicely to the CAGradientLayer property locations (though the % numbers are represented as values between 0 and 1).

The rgba(106, 164, 189, 0.5) 47.57% is red, green, and blue values of 106, 164, and 189, respectively, (each divided by 255). The 0.5 is an alpha of 50%. And the 47.57 is the position (47.57% of the way along the gradient).

Anyway, to render this, define an array of colors, array of positions, and the start and end of the gradient:

@IBDesignable class GradientView: UIView {
    override class var layerClass: AnyClass { CAGradientLayer.self }
    var gradientLayer: CAGradientLayer { layer as! CAGradientLayer }

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
    }

    func configure() {
        gradientLayer.colors = [#colorLiteral(red: 0.9607843137, green: 0.9960784314, blue: 1, alpha: 1), #colorLiteral(red: 0.7725490196, green: 0.9725490196, blue: 1, alpha: 1), #colorLiteral(red: 0.4156862745, green: 0.6431372549, blue: 0.7411764706, alpha: 0.5), #colorLiteral(red: 0.05490196078, green: 0.5450980392, blue: 0.6117647059, alpha: 1)].map { $0.cgColor }
        gradientLayer.locations = [0, 0, 0.4757, 0.8875]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
    }
}

If you want to see either the hex representation or integer representation of those colors, just double click on the color and tap on "Other" to see the RGB representations. E.g. I double clicked on the second color and I can see the #C5F8FF value:

enter image description here

A couple of final observations:

  • Note, I didn't just add a CAGradientLayer and set its frame. Instead, I created a view whose backing layer is a gradient. That way, if the view size changes because of constraints (or if you animate the size change), the size of the CAGradientLayer changes dynamically, too.

  • I made it @IBDesignable so I could see it in the storyboard. That’s not necessary, but is useful if using storyboards.

  • I wonder if your designer really meant to have both #F5FEFF and #C5F8FF at the 0% position. I suspect that was a mistake. (Figma makes it too easy to have multiple color data points in the gradient overlap with each other at either 0% or 100%.)

  • The CSS you've provided does not look syntactically correct. Notably, I don't know what to make of that #FFFFFF floating at the end (and your gradient points don’t go all the way to 100%). But, I don't think I need to know your full intent here ... you can just update the CAGradientLayer colors and locations arrays as you see fit. Just make sure they both have the same number of entries.

  • As you have noted, if you tap on the rightmost “Code” tab in the panel on the right in Figma, you can see an iOS code snippet. I would be wary of using that code, verbatim, in your app, because it (a) won’t use the UIView subclass outlined above, breaking if the view changes size or is animated; and (b) it will tend to use hard-coded values whereas you generally want to use constraints to dictate the layouts within iOS. Use this code snippet for inspiration, suggestions of possible API, etc., but I would not be inclined to use that exact code. Like all auto-generated code snippets, Figma’s suggested iOS code is not ideal.

Upvotes: 2

Julian Silvestri
Julian Silvestri

Reputation: 2027

let layerGradient = CAGradientLayer()
layerGradient.colors = [hexStringToUIColor(hex: "yourhex").cgColor,  hexStringToUIColor(hex: "yourhex").cgColor]
layerGradient.startPoint = CGPoint(x: 0, y: 0.5)
layerGradient.endPoint = CGPoint(x: 1, y: 0.5)
layerGradient.frame = CGRect(x: 0, y: 0, width: yourView.bounds.width, height: yourView.bounds.height)
self.yourView.layer.addSublayer(layerGradient)

Essentially you add a layer on top of your view which you then assign a start point and end point and provide colors to use.

This is the function used to convert hex strings to colors

func hexStringToUIColor (hex:String) -> UIColor {
    var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
    
    if (cString.hasPrefix("#")) {
        cString.remove(at: cString.startIndex)
    }
    
    if ((cString.count) != 6) {
        return UIColor.gray
    }
    
    var rgbValue:UInt64 = 0
    Scanner(string: cString).scanHexInt64(&rgbValue)
    
    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
}

Upvotes: 0

Related Questions