Créer par programme un UIView avec un dégradé de colors

J'essaie de générer une vue avec un arrière-plan de couleur de dégradé (une couleur unie à transparente) à l'exécution. Y a-t-il un moyen de le faire?

Objectif 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]; 

Rapide:

 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) 

Info : utilisez startPoint et endPoint pour changer la direction du dégradé .

Si d'autres vues sont ajoutées à cet UIView (comme un UILabel ), vous pouvez envisager de définir la couleur d'arrière-plan de ces UIView sur [UIColor clearColor] pour que la vue [UIColor clearColor] soit présentée à la place de la couleur d'arrière-plan des sous-vues . L'utilisation de clearColor a un léger clearColor performances.

C'est mon approche recommandée.

Pour favoriser la réutilisation, je dirais créer une catégorie de CAGradientLayer et append les gradients désirés comme methods de class. Spécifiez-les dans le file d'en- header comme ceci:

 #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 

Ensuite, dans votre file d'implémentation, spécifiez chaque dégradé avec cette syntaxe:

 + (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; } 

Ensuite, importez simplement cette catégorie dans votre ViewController ou toute autre subclasssubclass requirejse, et utilisez-la comme ceci:

 CAGradientLayer *backgroundLayer = [CAGradientLayer purpleGradientLayer]; backgroundLayer.frame = self.view.frame; [self.view.layer insertSublayer:backgroundLayer atIndex:0]; 

Comme je n'avais besoin que d'un type de dégradé dans mon application, j'ai créé une sous-class de UIView et préconfiguré le calque de dégradé à l'initialisation avec des colors fixes. Les initialiseurs de UIView appellent le configureGradientLayer -method, qui configure le 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 

Vous pouvez créer une class personnalisée GradientView :

Swift 3

 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.black.cgColor] } } 

Swift 2.2

 import UIKit class GradientView: UIView { override class func layerClass() -> AnyClass { return CAGradientLayer.self } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) let gradientLayer = self.layer as! CAGradientLayer gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor] } } 

Dans le storyboard, définissez le type de class sur toute vue pour laquelle vous souhaitez avoir un arrière-plan en dégradé:

entrez la description de l'image ici

C'est mieux de la manière suivante:

  • Pas besoin de définir le cadre de CLayer
  • Utilisez NSConstraint comme d'habitude sur l' UIView
  • Ne pas besoin de créer une sous-couche (less d'utilisation de la memory)

Essayez ça ça a marché comme un charme pour moi,

Objectif c

J'ai défini la couleur d'arrière-plan du dégradé RVB sur 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]; 

entrez la description de l'image ici

MISE À JOUR: – Swift3

Code: –

 let gradientLayer:CAGradientLayer = CAGradientLayer() gradientLayer.frame.size = self.gradientView.frame.size gradientLayer.colors = [UIColor.white.cgColor,UIColor.red.withAlphaComponent(1).cgColor] //Use diffrent colors self.gradientView.layer.addSublayer(gradientLayer) 

entrez la description de l'image ici

Vous pouvez append le sharepoint départ et de fin de la couleur du dégradé.

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

entrez la description de l'image ici

Pour plus de détails, référez-vous à CAGradientLayer Doc

J'espère que c'est de l'aide pour quelqu'un.

Rapidité de mise en œuvre

 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) 

J'ai implémenté ceci dans swift avec une extension:

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) } } 

Swift 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) } } 

Non, je peux définir un dégradé sur chaque vue comme ceci:

 myImageView.addGradientWithColor(UIColor.blue) 

J'ai étendu un peu la réponse acceptée en utilisant la fonctionnalité d'extension de Swift ainsi qu'une énumération.

Oh, et si vous utilisez Storyboard comme je le fais, assurez-vous d'appeler gradientBackground(from:to:direction:) dans viewDidLayoutSubviews() ou plus tard.

Swift 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) } } 

Ce que vous cherchez est CAGradientLayer . Chaque UIView a une couche – dans cette couche, vous pouvez append des sous-couches, tout comme vous pouvez append des sous-vues. Un type spécifique est CAGradientLayer , où vous lui donnez un tableau de colors à graduer.

Un exemple est ce wrapper simple pour une vue en dégradé:

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

Notez que vous devez inclure le framework QuartZCore pour accéder à toutes les parties de couche d'un UIView.

Une approche rapide

Cette réponse s'appuie sur les réponses ci-dessus et fournit une implémentation pour traiter le problème du gradient qui n'est pas correctement appliqué pendant la rotation. Il satisfait ce problème en changeant la couche de gradient en un carré de sorte que la rotation dans toutes les directions donne un gradient correct. La signature de la fonction inclut un argument variadique Swift qui permet de transmettre autant de CGColorRef (CGColor) que nécessaire (voir l'exemple d'utilisation). Un exemple est également fourni en tant qu'extension Swift afin que l'on puisse appliquer un dégradé à n'importe quel 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) } 

Utiliser:

dans viewDidLoad …

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

Extension

 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) } } 

Exemple d'utilisation de l'extension:

  override func viewDidLoad() { super.viewDidLoad() self.view.layer.configureGradientBackground(UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor, UIColor.whiteColor().CGColor) } 

Ce qui signifie que l'arrière-plan de gradient peut maintenant être appliqué à n'importe quel UIControl puisque tous les controls sont des UIViews (ou une sous-class) et tous les UIViews ont des CALayers.

Ma solution est de créer UIView sous-class CAGradientLayer avec CAGradientLayer accessible en tant que propriété readonly. Cela vous permettra de personnaliser votre dégradé comme vous le souhaitez et vous n'aurez pas besoin de gérer les modifications de layout vous-même. Implémentation de la sous-class:

 @interface GradientView : UIView @property (nonatomic, readonly) CAGradientLayer *gradientLayer; @end @implementation GradientView + (Class)layerClass { return [CAGradientLayer class]; } - (CAGradientLayer *)gradientLayer { return (CAGradientLayer *)self.layer; } @end 

Usage:

 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); 

Vue rapide simple basée sur la version de Yuchen

 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) } } 

Ensuite, vous pouvez utiliser gradientLayer après l'initialisation comme ça …

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

SWIFT 3

AJOUTER UNE COUCHE DE GRADIENT SUR VOTRE VUE

  • BIND VOTRE VUE OUTLET

     @IBOutlet var YOURVIEW : UIView! 
  • DÉFINIR CAGradientLayer ()

     var gradient = CAGradientLayer() 
  • VOICI LE CODE QUE VOUS DEVEZ ÉCRIRE DANS VOTRE VIDÉO

    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)

J'ai implémenté ceci dans mon code.

 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]; 

Maintenant, je peux voir un dégradé sur ma vue.

 extension UIView { func applyGradient(isTopBottom: Bool, colorArray: [UIColor]) { if let sublayers = layer.sublayers { let _ = sublayers.filter({ $0 is CAGradientLayer }).map({ $0.removeFromSuperlayer() }) } let gradientLayer = CAGradientLayer() gradientLayer.colors = colorArray.map({ $0.cgColor }) if isTopBottom { gradientLayer.locations = [0.0, 1.0] } else { //leftRight 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) } } 

USAGE

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

Dans Swift 3.1, j'ai ajouté cette extension à 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) } } 

que j'appelle ensuite avec

  class OverviewVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.view.gradientOfView(withColours: UIColor.red,UIColor.green, UIColor.blue) } } 

C'est une bonne idée d'appeler les solutions ci-dessus pour mettre à jour la couche sur le

 viewDidLayoutSubviews 

pour que les vues soient correctement mises à jour