Програмно створити UIView з кольоровим градієнтом


292

Я намагаюся створити подання з фоном градієнта кольору (суцільний колір до прозорого) під час виконання. Чи є спосіб зробити це?


2
Це маленький корисний інструмент, який створює код для вас градієнта itunes.apple.com/gb/app/gradient-creator/id1031070259?mt=12
burrGGG

Створення градієнтних кольорів за допомогою програми CAGradientLayer/ cagradientlayer
Макс

Відповіді:


694

Завдання-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має незначний хіт продуктивності.


13
+1 за найменшу кількість коду з усіх рішень. Я щойно додав до свого існуючого контролера перегляду, змінив 2 реф viewна self.viewта це спрацювало як шарм :)
Ергін

4
Також актуально, куди слід додати цей код. Мені потрібна була наступна публікація, щоб це працювало: stackoverflow.com/a/20059268/1480518
Дискотека Garrett

13
Це мені дуже допомогло! Пропала частина CGColor скрізь ще! Спасибі
Gyfis

48
Не забудьте використовувати "startPoint" і "endPoint" для зміни напрямку градієнта. Значення за замовчуванням (0,5, 0) і (0,5,1) - зверху вниз.
Валентин Шамардін

12
Коли мій UIView використовує AutoLayout, я також мав зателефонувати gradient.frame = view.boundsв viewDidAppear()і didRotateFromInterfaceOrientation()чи інакше градієнт не буде вибрано належним чином .
EricRobertBrewer

70

Ви можете створити спеціальний клас 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]
    }
}

На дошці розкадрування встановіть тип класу для будь-якого виду, для якого ви хочете мати градієнтний фон:

введіть тут опис зображення

Це краще наступними способами:

  • Не потрібно встановлювати кадр CLayer
  • Використовуйте NSConstraintяк завжди наUIView
  • Не потрібно створювати підшари (менше використання пам'яті)

1
У Swift 3 layerClassфункція більше не є функцією, вона є властивістю, тому вам доведеться переосмислити її як властивість: stackoverflow.com/questions/28786597/… . Крім того, ви повинні реалізувати override init(frame: CGRect), перевірити цей відповідь: stackoverflow.com/questions/27374330 / ... . Дякую!
LaloLoop

Привіт @LaloLoop, дякую за коментар! Я оновив код. Я не думаю, що мені доведеться перекривати init(frame:CGRect). Я перевірив оновлений код, і він працює чудово.
Ючен Чжун

@Yuchen Zhong Це збій у IB, але працює у додатку. Будь-які причини, чому він не відображається в IB, якщо @IBDesignableвін використовується?
Олександр Волков

@AlexanderVolkov Напевно, якесь інше питання? Ми використовували його так у розкладачі та, схоже, не мали жодних проблем. Ви можете встановити налагодження вашої розкадровки і побачити, яка лінія її розбиває.
Ючен Чжун

1
Найкраще рішення!
Баран Емре

40

Спробуйте це спрацювало як принадність для мене,

Мета 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];

введіть тут опис зображення

ОНОВЛЕНО: - 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)

введіть тут опис зображення

Ви можете додати початкову та кінцеву точку кольору градієнта.

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

введіть тут опис зображення

Детальніше описуйте в CAGradientLayer Doc

Сподіваюся, це допомога для когось.


36

Це мій рекомендований підхід.

Для сприяння повторному використанню я б сказав створити категорію 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];

куди слід поставити код, щоб ним користуватися? який спосіб життєвого циклу? viewdidappear робить це здається секунда занадто пізно. viewdidload і viewdidappear примушують його не працювати під час обертання. viewdidlayoutsubviews працює краще для обертання, але все ще виглядає трохи похмуро.
Адам Джонс

Я особисто вклав цеviewDidLoad
Сем Фішер

1
Коли я поставив це viewDidLoad, він не спрацював, якщо додаток було запущено в пейзажній орієнтації. Моє рішення полягало в тому, щоб зробити рамку фонового шару ширшою, ніж view.frame, щоб компенсувати інші орієнтації.
Адам Джонс

2
viewDidLoad працює, вам також потрібно встановити AutoResizingMask за допомогою [backgroundLayer setAutoresizingMask: UIViewAutoresizingFfleWidth | UIViewAutoresizingFfleHeight];
ekscrypto

21

Оскільки мені потрібен лише один тип градієнта протягом мого додатка, я створив підклас UIView і попередньо налаштував градієнтний шар при ініціалізації з фіксованими кольорами. Ініціалізатори UIView викликають configureGradientLayer -метод, який налаштовує 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схожа на ініціалізатор. Я не думаю, що це дуже підходить.
Світанок

@DawnSong Добре, я змінив його на "configureGradientLayer".
blauzahn

12

Швидке впровадження:

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

Я трохи продовжив прийняту відповідь, використовуючи функцію розширення Swift, а також перерахунок.

Так , і якщо ви використовуєте розкадровки , як я, не забудьте зателефонувати gradientBackground(from:to:direction:)в viewDidLayoutSubviews()або пізніше.

Швидкий 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

Я реалізував це швидко з розширенням:

Швидкий 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)

Дзвінок Swift3 повинен бути таким: myImageView.addGradientWithColor (колір: UIColor.blue)
mgyky

8

Швидкий підхід

Ця відповідь спирається на відповіді, наведені вище, та забезпечує реалізацію для вирішення проблеми градієнта, який не застосовується належним чином під час обертання. Він задовольняє цю проблему, змінюючи градієнтний шар на квадрат, так що обертання в усіх напрямках призводить до правильного градієнта. Підпис функції включає змінний аргумент Swift, який дозволяє передавати стільки CGColorRef (CGColor), скільки потрібно (див. Використання зразка). Наведено також приклад розширення Swift, щоб можна було застосувати градієнт до будь-якого 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, оскільки всі елементи керування - це UIView (або підклас), а всі UIView мають CALayers.

Швидкий 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)
}

5

Що ви шукаєте, так і є CAGradientLayer. У кожного UIViewє шар - у цей шар ви можете додавати підшари, як і ви можете додавати підпогляди. Один конкретний тип - це той CAGradientLayer, де ви надаєте йому масив кольорів для градієції між.

Одним із прикладів є ця проста обгортка для перегляду градієнта:

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

Зауважте, що вам потрібно включити рамку QuartZCore для доступу до всіх частин шару UIView.


4

Швидкий 4:

Відображає градієнт у ІБ правильно:

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

}

ВИКОРИСТАННЯ

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

3

Простий швидкий погляд на основі версії Ючен

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]

3

Моє рішення - створити 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);


2

SWIFT 3

Щоб додати шар градієнта у свій перегляд

  • Прив’яжіть свою розетку для перегляду

    @IBOutlet var YOURVIEW : UIView!
  • Визначте рівень CAGradientLayer ()

    var gradient = CAGradientLayer()
  • Ось код, який ви повинні написати у своєму переглядіDidLoad

    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
Я використовував такий підхід, змінивши "topview" на ім'я мого IBoutlet для мого перегляду. Я видалив рядок "SearchView".
jessi

Хороший план - можливо, також зауважте, що ви можете використовувати будь-який із встановлених градієнтів.кольорів. Отже, якщо ви коментуєте прості кольори gradient.colors, використовуючи названі кольори інтерфейсу, зображення є таким же, але якщо ви коментуєте інший, то градієнт кольору покладається на червоний на зелений. Користувачі можуть зробити будь-яку.
jessi

1

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

        }
}

0

Я реалізував це у своєму коді.

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

Тепер я бачу градієнт на своєму огляді.


0

Щоб надати кольору градієнта UIView (стрімкий 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.