Программно создать UIView с цветным градиентом
Я пытаюсь создать представление с градиентным цветом фона (от сплошного цвета до прозрачного) во время выполнения. Есть ли способ сделать это?
23 ответа
Objective-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];
Swift:
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
имеет небольшой удар по производительности.
Вы можете создать собственный класс GradientView
:
Свифт 4, Свифт 3
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
- Не нужно создавать подслои (меньше использования памяти)
Попробуй это, это сработало для меня
Цель С
Я установил цвет градиента 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
Надеюсь, что это помощь для кого-то.
Это мой рекомендуемый подход.
Чтобы способствовать повторному использованию, я бы сказал, создать категорию 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];
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)
}
}
ИСПОЛЬЗОВАНИЕ
someView.applyGradient(isTopBottom: true, colorArray: [.green, .blue])
Поскольку во всем приложении мне был нужен только один тип градиента, я создал подкласс 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
Я немного расширил принятый ответ, используя функциональность расширения 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)
}
}
Быстрая реализация:
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)
Я реализовал это в быстрой с расширением:
Свифт 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)
}
}
Нет, я могу установить градиент для каждого вида, как это:
myImageView.addGradientWithColor(UIColor.blue)
Быстрый подход
Этот ответ основан на ответах выше и обеспечивает реализацию для решения проблемы с неправильным применением градиента во время вращения. Это решает эту проблему, изменяя градиентный слой на квадрат, так что вращение во всех направлениях приводит к правильному градиенту. Сигнатура функции включает в себя переменный аргумент 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, поскольку все элементы управления являются UIViews (или подклассом), и все UIViews имеют CALayers.
Swift 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)
}
То, что вы ищете, это CAGradientLayer
, каждый UIView
имеет слой - в этот слой вы можете добавить подслои так же, как вы можете добавить подпредставления. Одним конкретным типом является CAGradientLayer
, где вы даете ему массив цветов для градиента.
Одним из примеров является эта простая оболочка для градиентного вида:
http://oleb.net/blog/2010/04/obgradientview-a-simple-uiview-wrapper-for-cagradientlayer/
Обратите внимание, что вам нужно включить платформу QuartZCore, чтобы получить доступ ко всем частям слоя UIView.
Это хорошая идея, чтобы вызвать решения выше, чтобы обновить слой на
viewDidLayoutSubviews
чтобы правильно обновить вид
Свифт 4:
Показывает градиент в 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]
}
}
Простой быстрый просмотр по версии Ючена
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)
}
}
Затем вы можете использовать градиентный слой после инициализации, как это...
someView.gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]
Мое решение состоит в том, чтобы создать 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);
SWIFT 3
Чтобы добавить слой градиента на ваш взгляд
Привязать свою точку зрения
@IBOutlet var YOURVIEW : UIView!
Определите CAGradientLayer()
var gradient = CAGradientLayer()
Вот код, который вы должны написать в вашем 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)
В 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)
}
}
Для скромниковUIView
подкласс в Swift:
class GradientView: UIView {
var startColor: UIColor?
var endColor: UIColor?
override func draw(_ rect: CGRect) {
// do not call super
if let startColor = startColor,
let endColor = endColor {
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)
gradient.colors = [startColor.cgColor, endColor.cgColor]
layer.addSublayer(gradient)
}
}
}
Использование с автоматической компоновкой:
let g = GradientView()
g.startColor = .red
g.endColor = .green
g.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(g)
// add constraints
Быстрый
Код функции: исходный код
вы можете использовать эту функцию для создания цвета градиента на виду.
self.gradientColor(yourView:View, startColor: UIColor.red, endColor: UIColor.white, colorAngle: 270)
Этот фреймворк хорош для градиентов и других модификаций пользовательского интерфейса в Historyboard: создавайте и прототипируйте индивидуальный пользовательский интерфейс, взаимодействие, навигацию, переходы и анимацию для готовых приложений App Store в конструкторе интерфейсов с помощью IBAnimatable.
При этом вы можете выбрать представление, установить класс AnimatableView и из свойства Interface Builder установить градиенты и результаты предварительного просмотра в реальном времени.
См. это , чтобы узнать, как применять градиенты к UIView.
Чтобы придать цвет градиента 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
}
Как пользоваться
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)
Я реализовал это в моем коде.
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];
Теперь я вижу градиент на моем видении.
Как предложил user173875 , рассмотрите возможность использования расширений,
это всегда поможет.
extension UIView {
func applyGradient(isVertical: Bool, colorArray: [UIColor]) {
layer.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])