J'essaie de générer une vue avec un arrière-plan de couleur dégradé (une couleur unie à transparente) au moment de l'exécution. Y a-t-il un moyen de le faire?
J'essaie de générer une vue avec un arrière-plan de couleur dégradé (une couleur unie à transparente) au moment de l'exécution. Y a-t-il un moyen de le faire?
Réponses:
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)
Info : utilisez startPoint et endPoint pour changer la direction du dégradé .
Si d'autres vues y sont ajoutées UIView
(telles que a UILabel
), vous pouvez envisager de définir la couleur d'arrière-plan de celles UIView
-ci pour [UIColor clearColor]
que la vue dégradée soit présentée à la place de la couleur d'arrière-plan des sous-vues. L'utilisation clearColor
a un léger impact sur les performances.
view
en self.view
et cela a fonctionné comme un charme :)
gradient.frame = view.bounds
en viewDidAppear()
et didRotateFromInterfaceOrientation()
ou bien le gradient ne serait pas la bonne taille.
Vous pouvez créer une classe personnalisée GradientView
:
Swift 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]
}
}
Dans le storyboard, définissez le type de classe sur n'importe quelle vue que vous souhaitez avoir un arrière-plan dégradé:
C'est mieux des manières suivantes:
CLayer
NSConstraint
comme d'habitude sur leUIView
layerClass
n'est plus une fonction, c'est une propriété, vous devez donc la remplacer comme une propriété: stackoverflow.com/questions/28786597/… . Vous devez également implémenter override init(frame: CGRect)
, vérifiez cette réponse: stackoverflow.com/questions/27374330/… . Merci!
init(frame:CGRect)
. J'ai testé le code mis à jour et cela fonctionne très bien.
@IBDesignable
est utilisé?
Essayez ça a fonctionné 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];
MISE À JOUR: - Swift3 +
Code : -
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)
Vous pouvez ajouter le point de 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)
Pour plus de détails, voir CAGradientLayer Doc
J'espère que c'est de l'aide pour quelqu'un.
C'est mon approche recommandée.
Pour promouvoir la réutilisabilité, je dirais de créer une catégorie CAGradientLayer
et d'ajouter vos dégradés souhaités comme méthodes de classe. Spécifiez-les dans le header
fichier 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 fichier d'implémentation, spécifiez chaque gradient 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 exigence subclass
, et utilisez-la comme ceci:
CAGradientLayer *backgroundLayer = [CAGradientLayer purpleGradientLayer];
backgroundLayer.frame = self.view.frame;
[self.view.layer insertSublayer:backgroundLayer atIndex:0];
viewDidLoad
viewDidLoad
, cela n'a pas fonctionné si l'application a été lancée en orientation paysage. Ma solution était de rendre le cadre du calque d'arrière-plan plus large que le cadre view.frame pour compenser les autres orientations.
Comme je n'avais besoin que d'un seul type de dégradé dans mon application, j'ai créé une sous-classe d'UIView et préconfiguré la couche de dégradé lors de l'initialisation avec des couleurs fixes. Les initialiseurs d'UIView appellent la méthode configureGradientLayer , 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
initGradientLayer
est similaire à un initialiseur. Je ne pense pas que ce soit très approprié.
Mise en œuvre rapide:
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 un peu étendu 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:)
à 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)
}
}
J'ai implémenté cela en 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)
Une approche rapide
Cette réponse s'appuie sur les réponses ci-dessus et fournit une implémentation permettant de traiter le problème de la mauvaise application du gradient pendant la rotation. Il résout ce problème en changeant la couche de dégradé en un carré de sorte que la rotation dans toutes les directions entraîne un gradient correct. La signature de la fonction inclut un argument variadique Swift qui permet de passer autant de CGColorRef (CGColor) que nécessaire (voir exemple d'utilisation). Un exemple d'extension Swift est également fourni afin que l'on puisse appliquer un dégradé à n'importe quelle vue UIV.
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)
}
Implémentation d'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 de cas d'utilisation d'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 dégradé peut maintenant être appliqué à n'importe quel UIControl car tous les contrôles sont des UIViews (ou une sous-classe) et tous les UIViews ont des CALayers.
Swift 4
Implémentation d'extension
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)
}
}
Exemple de cas d'utilisation d'extension:
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.configureGradientBackground(UIColor.purple.cgColor, UIColor.blue.cgColor, UIColor.white.cgColor)
}
Ce que vous cherchez, c'est CAGradientLayer
. Chacun UIView
a une couche - dans cette couche, vous pouvez ajouter des sous-couches, tout comme vous pouvez ajouter des sous-vues. Un type spécifique est le CAGradientLayer
, où vous lui donnez un tableau de couleurs à graduer.
Un exemple est ce simple wrapper 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 afin d'accéder à toutes les parties de couche d'une UIView.
Swift 4:
Affiche correctement le gradient dans 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]
}
}
extension UIView {
func applyGradient(isVertical: Bool, colorArray: [UIColor]) {
if let sublayers = layer.sublayers {
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)
}
}
USAGE
someView.applyGradient(isVertical: true, colorArray: [.green, .blue])
Vue simple et rapide 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 ceci ...
someView.gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]
Ma solution est de créer une UIView
sous-classe avec CAGradientLayer
accessible en tant que propriété en lecture seule. Cela vous permettra de personnaliser votre dégradé comme vous le souhaitez et vous n'avez pas besoin de gérer vous-même les modifications de mise en page. Mise en œuvre de la sous-classe:
@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);
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
SWIFT 3
Pour ajouter un calque de dégradé sur votre vue
Liez votre point de vue
@IBOutlet var YOURVIEW : UIView!
Définissez le CAGradientLayer ()
var gradient = CAGradientLayer()
Voici le code que vous devez écrire dans votre 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)
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)
}
}
J'ai implémenté cela 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.
Pour donner un dégradé de couleur à 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
}
Comment utiliser
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)