Créer une extension UIView pour ajouter un Gradient
Lorsque vous ajoutez une couleur à votre UIView, vous utilisez backgroundColor, qui va ajouter une couleur unie à votre vue. Savez-vous qu’il est aussi possible d’ajouter un déradé de couleurs à votre vue? Ce dégradé (gradient en anglais) peut s’ajouter facilement avec Swift en utilisant un CAGradientLayer et en l’ajoutant en tant que Sublayer à votre vue. Pour cela, il faut:
- Déclarer et initialiser votre gradient de type CAGradientLayer
- lui donner une forme
- ajouter des couleurs (de type CGColor)
- (optionnel) ajouter la position de ces couleurs. Ceci est utile si on utilise plus de 2 couleurs.
- un point de départ du gradient
- un point de fin du gradient
- Enfin ajouter le gradient en tant que sublayer de la vue
Dans le code, voici ce que cela donne:
override func viewDidLoad() {
super.viewDidLoad()
let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.white.cgColor, UIColor.lightGray.cgColor]
gradient.locations = [0, 1]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 1)
view.layer.addSublayer(gradient)
}
Quelques petites remarques:
gradient.locations: Les valeurs se situent à un minimum de 0 et un Maximum de 1. Le milieu sera donc 0.5.
passons maintenant aux startPoint et endPoint. La aussi les valeurs se situent entre 0 et 1.
- 0 est égal à x = 0 et y = 0
- 1 est égal à x = valeur max de la largeur et y = valeur max de la hauteur
Ok, tout cela est très simple et très facile à réaliser. Par contre, si vous voulez créer plusieurs gradient dans votre application, il faudra écrire plusieurs fois le même code et ceci va à l’encontre du principe DRY (Don’t Repeat Yourself). Ne Pas Répéter le Code!
Si nous créons une fonction comme extension de UIView, il sera possible de créer des gradients dans toute notre application sans avoir à répéter notre code.
De quels paramètres avons nous avoir besoin pour créer notre fonction gradient?
- Notre gradient aura la même taille que notre vue, nous n’avons pas besoin de créer un paramètre frame dans notre function.
- Nous aurons besoin d’un array de couleurs en CGColor
- Nous allons aussi avoir un array de NSNumber pour déterminer le gradient.locations ou en d’autres termes la position des couleurs sur la ligne entre el startPoint et le endPoint.
- Concernant les startPoint et les endPoint, nous allons créer un enum des différentes possibilités de disposition de notre dégradé
Voici notre Enum:
enum Orientation {
case horizontal
case vertical
case diagonalTopLeft
case diagonalTopRight
}
Une fois que nous avons notre enum, créons la fonction avec les paramètres listés ci-dessus:
extension UIView {
func creerGradient(couleurs: [CGColor], orientation: Orientation, position: [NSNumber]? = nil) {
}
}
Ok, Nous avons notre fonction! Maintenant passons au code dans la fonction. On va commencer par créer un CAGradientLayer comme ceci: let gradient = CAGradientLayer().
la frame de ce gradient sera égale à bounds. Comme nous somme dans une extension de UIView, bounds se réfère aux bounds la vue sur laquelle nous allons appliquer le gradient. gradient.colors sera égal à couleurs.
Pour les positions: Nous allons vérifier si position n’est pas nil et si le nombre d’éléments dans l’array couleurs est égal au nombre d’éléments dans l’array position. Si ces 2 conditions sont réunies, nous pouvons ajouter l’array position à gradient.locations
Concernant l’orientation de notre gradient, nous allons créer une fonction qui va retourner 2 CGPoint selon l’orientation (un startPoint et un endPoint).
Enfin, nous pourrons ajouter le gradient en tant que sublayer.
Voici tout d’abord la fonction pour convertir l’orientation en 2 CGPoint:
func convertirOrientation(_ orientation: Orientation) -> (CGPoint, CGPoint){
switch orientation {
case .horizontal: return(CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 0))
case .vertical: return(CGPoint(x: 0, y: 0), CGPoint(x: 0, y: 1))
case .diagonalTopLeft: return(CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 1))
case .diagonalTopRight: return(CGPoint(x: 1, y: 0), CGPoint(x: 0, y: 1))
}
}
Ensuite nous pouvons finaliser notre fonction creerGradient:
import UIKit
enum Orientation {
case horizontal
case vertical
case diagonalTopLeft
case diagonalTopRight
}
extension UIView {
func creerGradient(couleurs: [CGColor], orientation: Orientation, position: [NSNumber]? = nil) {
let gradient = CAGradientLayer()
gradient.frame = bounds
(gradient.startPoint, gradient.endPoint) = convertirOrientation(orientation)
gradient.colors = couleurs
if let locations = position, locations.count == couleurs.count {
gradient.locations = locations
}
layer.addSublayer(gradient)
}
func convertirOrientation(_ orientation: Orientation) -> (CGPoint, CGPoint){
switch orientation {
case .horizontal: return(CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 0))
case .vertical: return(CGPoint(x: 0, y: 0), CGPoint(x: 0, y: 1))
case .diagonalTopLeft: return(CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 1))
case .diagonalTopRight: return(CGPoint(x: 1, y: 0), CGPoint(x: 0, y: 1))
}
}
}
Notre extension est finie, il nous reste plus qu’à l’utiliser! Voici ce que cela donnerait dans un viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
view.creerGradient(couleurs: [UIColor.white.cgColor, UIColor.blue.cgColor, UIColor.red.cgColor], orientation: .vertical, position: [0, 0.25, 1])
}