Créer par programme une UIView avec un dégradé de couleurs


292

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?


2
Ceci est un petit outil utile qui crée du code de dégradé pour vous itunes.apple.com/gb/app/gradient-creator/id1031070259?mt=12
burrGGG

Création de couleurs dégradées à l'aide de CAGradientLayer appcoda.com/cagradientlayer
Max

Réponses:


694

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 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 clearColora un léger impact sur les performances.


13
+1 pour la quantité de code la plus courte de toutes les solutions. J'ai juste ajouté à mon contrôleur de vue existant, changé les 2 refs viewen self.viewet cela a fonctionné comme un charme :)
Ergin

4
Il est également pertinent de savoir où ajouter ce code. J'avais besoin du post suivant pour que cela fonctionne: stackoverflow.com/a/20059268/1480518
Garrett Disco

13
Cela m'a beaucoup aidé! Vous avez manqué la partie CGColor partout ailleurs! Merci
Gyfis

48
N'oubliez pas d'utiliser 'startPoint' et 'endPoint' pour changer la direction du dégradé. Les valeurs par défaut sont (0,5, 0) et (0,5,1) - de haut en bas.
Valentin Shamardin

12
Quand mon UIView utilise AutoLayout, je devais aussi appeler gradient.frame = view.boundsen viewDidAppear()et didRotateFromInterfaceOrientation()ou bien le gradient ne serait pas la bonne taille.
EricRobertBrewer

70

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é:

entrez la description de l'image ici

C'est mieux des manières suivantes:

  • Pas besoin de régler le cadre de CLayer
  • Utilisez NSConstraintcomme d'habitude sur leUIView
  • Pas besoin de créer des sous-couches (moins d'utilisation de la mémoire)

1
Sur Swift 3, la layerClassn'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!
LaloLoop

Bonjour @LaloLoop, merci pour le commentaire! J'ai mis à jour le code. Je ne pense pas que je doive passer outre init(frame:CGRect). J'ai testé le code mis à jour et cela fonctionne très bien.
Yuchen Zhong

@Yuchen Zhong Il se bloque dans IB, mais fonctionne dans l'application. Y a-t-il des raisons pour lesquelles il n'est pas rendu dans IB s'il @IBDesignableest utilisé?
Alexander Volkov

@AlexanderVolkov Probablement un autre problème? Nous l'avons utilisé comme tel dans le storyboard et ne semble pas avoir de problème cependant. Vous pouvez déboguer votre storyboard et voir quelle ligne le plante.
Yuchen Zhong

1
Meilleure solution !
Baran Emre

40

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

entrez la description de l'image ici

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)

entrez la description de l'image ici

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)

entrez la description de l'image ici

Pour plus de détails, voir CAGradientLayer Doc

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


36

C'est mon approche recommandée.

Pour promouvoir la réutilisabilité, je dirais de créer une catégorie CAGradientLayeret d'ajouter vos dégradés souhaités comme méthodes de classe. Spécifiez-les dans le headerfichier 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 ViewControllerou 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];

où mettre le code pour l'utiliser? quelle méthode de cycle de vie? viewdidappear fait apparaître une seconde trop tard. viewdidload et viewdidappear l'empêchent de fonctionner lors de la rotation. viewdidlayoutsubviews fonctionne mieux pour la rotation mais finit toujours par sembler un peu saccadé.
Adam Johns

Personnellement, je l'ai misviewDidLoad
Sam Fischer

1
Quand je l'ai mis 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.
Adam Johns

2
viewDidLoad fonctionne, il vous suffit également de définir AutoResizingMask en utilisant [backgroundLayer setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
ekscrypto

21

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

Le nom de la méthode initGradientLayerest similaire à un initialiseur. Je ne pense pas que ce soit très approprié.
DawnSong

@DawnSong Bon point, je l'ai changé en «configureGradientLayer».
blauzahn

12

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)

11

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

10

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)

L'appel Swift3 doit être comme: myImageView.addGradientWithColor (couleur: UIColor.blue)
mgyky

8

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

5

Ce que vous cherchez, c'est CAGradientLayer. Chacun UIViewa 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.


4

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

4
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])

3

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]

3

Ma solution est de créer une UIViewsous-classe avec CAGradientLayeraccessible 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);

3

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


2

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)


1
J'ai utilisé cette approche, en changeant "topview" pour le nom de mon IBoutlet pour ma vue. J'ai supprimé la ligne "SearchView".
jessi

Bon plan - notez peut-être aussi que vous pouvez utiliser l'une des configurations de gradient.colors. Donc, si vous commentez les dégradés.couleurs simples en utilisant des couleurs d'interface utilisateur nommées, l'image est la même, mais si vous commentez l'autre, le dégradé de couleurs dépend alors du rouge au vert. Les utilisateurs peuvent faire l'un ou l'autre.
jessi

1

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)

        }
}

0

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.


0

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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.