以编程方式创建一个带有颜色梯度的UIView

我试图在运行时生成一个渐变颜色背景(纯色到透明)的视图。有办法做到吗?

279357 次浏览

你要找的是CAGradientLayer。每个UIView都有一个层——你可以在这个层中添加子层,就像你可以添加子视图一样。一个特定的类型是CAGradientLayer,你给它一个颜色数组来渐变。

一个例子是这个简单的渐变视图包装器:

http://oleb.net/blog/2010/04/obgradientview-a-simple-uiview-wrapper-for-cagradientlayer/

注意,为了访问UIView的所有层部分,你需要包括QuartZCore框架。

objective - c:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
CAGradientLayer *gradient = [CAGradientLayer layer];


gradient.frame = view.bounds;
gradient.colors = @[(id)[UIColor whiteColor].CGColor, (id)[UIColor blackColor].CGColor];


[view.layer insertSublayer:gradient atIndex:0];

迅速:

let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
let gradient = CAGradientLayer()


gradient.frame = view.bounds
gradient.colors = [UIColor.white.cgColor, UIColor.black.cgColor]


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

信息: 使用startPoint和endPoint 改变梯度方向

如果有任何其他视图添加到这个UIView上(比如UILabel),你可能想要考虑将这些UIView的背景色设置为[UIColor clearColor],这样渐变视图就会显示出来,而不是子视图的背景色。使用clearColor会有轻微的性能损失。

这是我推荐的方法。

为了提高可重用性,我会说创建一个CAGradientLayer的类别,并添加你想要的梯度作为类方法。在header文件中像这样指定它们:

#import <QuartzCore/QuartzCore.h>


@interface CAGradientLayer (SJSGradients)


+ (CAGradientLayer *)redGradientLayer;
+ (CAGradientLayer *)blueGradientLayer;
+ (CAGradientLayer *)turquoiseGradientLayer;
+ (CAGradientLayer *)flavescentGradientLayer;
+ (CAGradientLayer *)whiteGradientLayer;
+ (CAGradientLayer *)chocolateGradientLayer;
+ (CAGradientLayer *)tangerineGradientLayer;
+ (CAGradientLayer *)pastelBlueGradientLayer;
+ (CAGradientLayer *)yellowGradientLayer;
+ (CAGradientLayer *)purpleGradientLayer;
+ (CAGradientLayer *)greenGradientLayer;


@end

然后在你的实现文件中,用下面的语法指定每个渐变:

+ (CAGradientLayer *)flavescentGradientLayer
{
UIColor *topColor = [UIColor colorWithRed:1 green:0.92 blue:0.56 alpha:1];
UIColor *bottomColor = [UIColor colorWithRed:0.18 green:0.18 blue:0.18 alpha:1];


NSArray *gradientColors = [NSArray arrayWithObjects:(id)topColor.CGColor, (id)bottomColor.CGColor, nil];
NSArray *gradientLocations = [NSArray arrayWithObjects:[NSNumber numberWithInt:0.0],[NSNumber numberWithInt:1.0], nil];


CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = gradientColors;
gradientLayer.locations = gradientLocations;


return gradientLayer;
}

然后简单地在你的ViewController或任何其他需要的subclass中导入这个类别,并像这样使用它:

CAGradientLayer *backgroundLayer = [CAGradientLayer purpleGradientLayer];
backgroundLayer.frame = self.view.frame;
[self.view.layer insertSublayer:backgroundLayer atIndex:0];
因为我只需要一种类型的梯度整个我的应用程序,我创建了一个UIView的子类,并在初始化固定的颜色预配置梯度层。 UIView的初始化器调用__abc0 -方法,它配置CAGradientLayer:

DDGradientView.h:

#import <UIKit/UIKit.h>


@interface DDGradientView : UIView {


}
@end

DDGradientView.m:

#import "DDGradientView.h"


@implementation DDGradientView


// Change the views layer class to CAGradientLayer class
+ (Class)layerClass
{
return [CAGradientLayer class];
}


- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self) {
[self configureGradientLayer];
}
return self;
}


- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
[self configureGradientLayer];
}
return self;
}


// Make custom configuration of your gradient here
- (void)configureGradientLayer {
CAGradientLayer *gLayer = (CAGradientLayer *)self.layer;
gLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor lightGrayColor] CGColor], nil];
}
@end

迅速实现:

var gradientLayerView: UIView = UIView(frame: CGRectMake(0, 0, view.bounds.width, 50))
var gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = gradientLayerView.bounds
gradient.colors = [UIColor.grayColor().CGColor, UIColor.clearColor().CGColor]
gradientLayerView.layer.insertSublayer(gradient, atIndex: 0)
self.view.layer.insertSublayer(gradientLayerView.layer, atIndex: 0)

快速的方法

这个答案建立在上面的答案之上,并提供了解决旋转过程中梯度没有被正确应用的问题的实现。它通过将梯度层更改为正方形来满足这个问题,以便在所有方向上旋转产生正确的梯度。函数签名包括一个Swift可变参数,允许传入任意数量的CGColorRef (CGColor)(参见示例用法)。还提供了一个例子,作为一个快速扩展,这样就可以应用渐变到任何UIView。

   func configureGradientBackground(colors:CGColorRef...){


let gradient: CAGradientLayer = CAGradientLayer()
let maxWidth = max(self.view.bounds.size.height,self.view.bounds.size.width)
let squareFrame = CGRect(origin: self.view.bounds.origin, size: CGSizeMake(maxWidth, maxWidth))
gradient.frame = squareFrame


gradient.colors = colors
view.layer.insertSublayer(gradient, atIndex: 0)
}

使用方法:

在viewDidLoad…

  override func viewDidLoad() {
super.viewDidLoad()
configureGradientBackground(UIColor.redColor().CGColor, UIColor.whiteColor().CGColor)
}

扩展的实现

extension CALayer {




func configureGradientBackground(colors:CGColorRef...){


let gradient = CAGradientLayer()


let maxWidth = max(self.bounds.size.height,self.bounds.size.width)
let squareFrame = CGRect(origin: self.bounds.origin, size: CGSizeMake(maxWidth, maxWidth))
gradient.frame = squareFrame


gradient.colors = colors


self.insertSublayer(gradient, atIndex: 0)
}


}

扩展用例示例:

 override func viewDidLoad() {
super.viewDidLoad()


self.view.layer.configureGradientBackground(UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor, UIColor.whiteColor().CGColor)
}

这意味着渐变背景现在可以应用到任何UIControl,因为所有的控件都是UIViews(或子类),所有的UIViews都有calayer。

斯威夫特4

扩展的实现

extension CALayer {
public func configureGradientBackground(_ colors:CGColor...){


let gradient = CAGradientLayer()


let maxWidth = max(self.bounds.size.height,self.bounds.size.width)
let squareFrame = CGRect(origin: self.bounds.origin, size: CGSize(width: maxWidth, height: maxWidth))
gradient.frame = squareFrame


gradient.colors = colors


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

扩展用例示例:

override func viewDidLoad() {
super.viewDidLoad()


self.view.layer.configureGradientBackground(UIColor.purple.cgColor, UIColor.blue.cgColor, UIColor.white.cgColor)
}

你可以创建一个自定义类GradientView:

斯威夫特5

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


required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let gradientLayer = layer as! CAGradientLayer
gradientLayer.colors = [UIColor.white.cgColor, UIColor.black.cgColor]
}
}

在故事板中,将类类型设置为你想要有渐变背景的任何视图:

enter image description here

这在以下方面是更好的:

  • 不需要设置CLayer
  • UIView上像往常一样使用NSConstraint
  • 不需要创建子层(更少的内存使用)

基于Yuchen版本的简单swift视图

class GradientView: UIView {
override class func layerClass() -> AnyClass { return CAGradientLayer.self }


lazy var gradientLayer: CAGradientLayer = {
return self.layer as! CAGradientLayer
}()


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


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


}

然后你可以在初始化后使用gradientLayer,像这样…

someView.gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]

我已经在swift中实现了一个扩展:

斯威夫特3

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


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

斯威夫特2.2

extension UIView {
func addGradientWithColor(color: UIColor) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [UIColor.clearColor().CGColor, color.CGColor]


self.layer.insertSublayer(gradient, atIndex: 0)
}
}

不,我可以像这样在每个视图上设置渐变:

myImageView.addGradientWithColor(UIColor.blue)

我已经在代码中实现了这一点。

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 31.0f)];
view1.backgroundColor = [UIColor clearColor];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view1.bounds;
UIColor *topColor = [UIColor colorWithRed:132.0/255.0 green:222.0/255.0 blue:109.0/255.0 alpha:1.0];
UIColor *bottomColor = [UIColor colorWithRed:31.0/255.0 green:150.0/255.0 blue:99.0/255.0 alpha:1.0];
gradient.colors = [NSArray arrayWithObjects:(id)[topColor CGColor], (id)[bottomColor CGColor], nil];




[view1.layer insertSublayer:gradient atIndex:0];

现在我可以在视图中看到渐变。

试试这个对我来说很有魔力,

Objective - C

我已经将RGB渐变背景色设置为UIview

   UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,35)];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.startPoint = CGPointZero;
gradient.endPoint = CGPointMake(1, 1);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:34.0/255.0 green:211/255.0 blue:198/255.0 alpha:1.0] CGColor],(id)[[UIColor colorWithRed:145/255.0 green:72.0/255.0 blue:203/255.0 alpha:1.0] CGColor], nil];
[view.layer addSublayer:gradient];

enter image description here

< >强更新:- Swift3 + < / >强

代码: -

 var gradientView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 35))
let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame.size = self.gradientView.frame.size
gradientLayer.colors =
[UIColor.white.cgColor,UIColor.red.withAlphaComponent(1).cgColor]
//Use diffrent colors
gradientView.layer.addSublayer(gradientLayer)

enter image description here

你可以添加渐变颜色的起点和终点。

  gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)

enter image description here

更多详细信息请参考CAGradientLayer医生

希望这对一些人有所帮助。

我的解决方案是创建UIView子类,其中CAGradientLayer可作为只读属性访问。这将允许你自定义你想要的渐变,你不需要自己处理布局变化。子类实现:

@interface GradientView : UIView


@property (nonatomic, readonly) CAGradientLayer *gradientLayer;


@end


@implementation GradientView


+ (Class)layerClass
{
return [CAGradientLayer class];
}


- (CAGradientLayer *)gradientLayer
{
return (CAGradientLayer *)self.layer;
}


@end

用法:

self.iconBackground = [GradientView new];
[self.background addSubview:self.iconBackground];
self.iconBackground.gradientLayer.colors = @[(id)[UIColor blackColor].CGColor, (id)[UIColor whiteColor].CGColor];
self.iconBackground.gradientLayer.startPoint = CGPointMake(1.0f, 1.0f);
self.iconBackground.gradientLayer.endPoint = CGPointMake(0.0f, 0.0f);
extension UIView {


func applyGradient(isVertical: Bool, colorArray: [UIColor]) {
layer.sublayers?.filter({ $0 is CAGradientLayer }).forEach({ $0.removeFromSuperlayer() })
         

let gradientLayer = CAGradientLayer()
gradientLayer.colors = colorArray.map({ $0.cgColor })
if isVertical {
//top to bottom
gradientLayer.locations = [0.0, 1.0]
} else {
//left to right
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
}
        

backgroundColor = .clear
gradientLayer.frame = bounds
layer.insertSublayer(gradientLayer, at: 0)
}


}

使用

someView.applyGradient(isVertical: true, colorArray: [.green, .blue])

在Swift 3.1 我已经添加了这个扩展到UIView

import Foundation
import UIKit
import CoreGraphics




extension UIView {
func gradientOfView(withColours: UIColor...) {


var cgColours = [CGColor]()


for colour in withColours {
cgColours.append(colour.cgColor)
}
let grad = CAGradientLayer()
grad.frame = self.bounds
grad.colors = cgColours
self.layer.insertSublayer(grad, at: 0)
}
}

然后我用它来调用

    class OverviewVC: UIViewController {


override func viewDidLoad() {
super.viewDidLoad()


self.view.gradientOfView(withColours: UIColor.red,UIColor.green, UIColor.blue)


}
}

斯威夫特3

在视图上添加一个渐变层

  • < p > 绑定视图输出口

    @IBOutlet var YOURVIEW : UIView!
    
  • Define the CAGradientLayer()

    var gradient = CAGradientLayer()
    
  • Here is the code you have to write in your viewDidLoad

    YOURVIEW.layoutIfNeeded()

    gradient.startPoint = CGPoint(x: CGFloat(0), y: CGFloat(1)) gradient.endPoint = CGPoint(x: CGFloat(1), y: CGFloat(0)) gradient.frame = YOURVIEW.bounds gradient.colors = [UIColor.red.cgColor, UIColor.green.cgColor] gradient.colors = [ UIColor(red: 255.0/255.0, green: 56.0/255.0, blue: 224.0/255.0, alpha: 1.0).cgColor,UIColor(red: 86.0/255.0, green: 13.0/255.0, blue: 232.0/255.0, alpha: 1.0).cgColor,UIColor(red: 16.0/255.0, green: 173.0/255.0, blue: 245.0/255.0, alpha: 1.0).cgColor] gradient.locations = [0.0 ,0.6 ,1.0] YOURVIEW.layer.insertSublayer(gradient, at: 0)

我已经使用Swift的扩展功能和枚举扩展了接受的答案。

哦,如果你像我一样使用Storyboard,一定要在viewDidLayoutSubviews()或以后调用gradientBackground(from:to:direction:)

斯威夫特3

enum GradientDirection {
case leftToRight
case rightToLeft
case topToBottom
case bottomToTop
}


extension UIView {
func gradientBackground(from color1: UIColor, to color2: UIColor, direction: GradientDirection) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [color1.cgColor, color2.cgColor]


switch direction {
case .leftToRight:
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
case .rightToLeft:
gradient.startPoint = CGPoint(x: 1.0, y: 0.5)
gradient.endPoint = CGPoint(x: 0.0, y: 0.5)
case .bottomToTop:
gradient.startPoint = CGPoint(x: 0.5, y: 1.0)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
default:
break
}


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

调用上面的解决方案来更新层是一个好主意

viewDidLayoutSubviews 

正确地更新视图

斯威夫特4:

正确显示IB中的梯度:

@IBDesignable public class GradientView: UIView {


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


required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configureGradientLayer()
}


public override init(frame: CGRect) {
super.init(frame: frame)
configureGradientLayer()
}


func configureGradientLayer() {
let gradientLayer = layer as! CAGradientLayer
gradientLayer.colors = [UIColor(hex: 0x003399).cgColor, UIColor(hex: 0x00297b).cgColor]
}
}

给UIView渐变颜色(swift 4.2)

func makeGradientLayer(`for` object : UIView, startPoint : CGPoint, endPoint : CGPoint, gradientColors : [Any]) -> CAGradientLayer {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = gradientColors
gradient.locations = [0.0 , 1.0]
gradient.startPoint = startPoint
gradient.endPoint = endPoint
gradient.frame = CGRect(x: 0, y: 0, w: object.frame.size.width, h: object.frame.size.height)
return gradient
}

如何使用

let start : CGPoint = CGPoint(x: 0.0, y: 1.0)
let end : CGPoint = CGPoint(x: 1.0, y: 1.0)


let gradient: CAGradientLayer = makeGradientLayer(for: cell, startPoint: start, endPoint: end, gradientColors: [
UIColor(red:0.92, green:0.07, blue:0.4, alpha:1).cgColor,
UIColor(red:0.93, green:0.11, blue:0.14, alpha:1).cgColor
])


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

这个框架适用于Historyboard: 设计和原型定制的UI,交互,导航,过渡和动画在接口生成器与IBAnimatable应用程序商店就绪的应用程序。中的渐变和其他UI修改

有了这个,你可以选择一个视图,将类设置为AnimatableView,并从Interface Builder属性设置梯度和实时预览结果。

参见了解如何将渐变应用到UIView。