Próbuję wygenerować widok z tłem w kolorze gradientu (od jednolitego koloru do przezroczystego) w czasie wykonywania. Czy jest na to sposób?
Próbuję wygenerować widok z tłem w kolorze gradientu (od jednolitego koloru do przezroczystego) w czasie wykonywania. Czy jest na to sposób?
Odpowiedzi:
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)
Informacje : użyj startPoint i endPoint, aby zmienić kierunek gradientu .
Jeśli dodano do niego jakiekolwiek inne widoki UIView
(takie jak a UILabel
), możesz rozważyć ustawienie koloru tła tych elementów UIView
, aby [UIColor clearColor]
widok gradientu był wyświetlany zamiast koloru tła dla widoków podrzędnych. Korzystanie clearColor
ma niewielki spadek wydajności.
view
na self.view
i działało to jak urok :)
gradient.frame = view.bounds
w viewDidAppear()
aw didRotateFromInterfaceOrientation()
albo gradient nie będzie odpowiedniej wielkości.
Możesz utworzyć niestandardową klasę GradientView
:
Szybki 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]
}
}
W scenorysie ustaw typ klasy na dowolny widok, który ma mieć tło gradientowe:
Jest to lepsze na następujące sposoby:
CLayer
NSConstraint
jak zwykle naUIView
layerClass
nie jest już funkcją, jest właściwością, więc musisz ją zastąpić jak właściwość: stackoverflow.com/questions/28786597/… . Również trzeba wdrożyć override init(frame: CGRect)
, sprawdź tę odpowiedź: stackoverflow.com/questions/27374330/... . Dzięki!
init(frame:CGRect)
. Przetestowałem zaktualizowany kod i działa dobrze.
@IBDesignable
jest używany?
Spróbuj To działało jak urok dla mnie,
Cel C
Mam ustawiony RGB gradientu kolor tła do 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];
AKTUALIZACJA: - Swift3 +
Kod : -
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)
Możesz dodać punkt początkowy i końcowy koloru gradientu.
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
Aby uzyskać więcej szczegółowych informacji, patrz CAGradientLayer Doc
Mam nadzieję, że to jest pomoc dla kogoś.
To jest moje zalecane podejście.
Aby promować wielokrotne użycie, powiedziałbym, że należy utworzyć kategorię CAGradientLayer
i dodać pożądane gradienty jako metody klasowe. Określ je w header
pliku w następujący sposób:
#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
Następnie w pliku implementacji określ każdy gradient za pomocą następującej składni:
+ (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;
}
Następnie po prostu zaimportuj tę kategorię do swojej ViewController
lub innej wymaganej subclass
i użyj jej w następujący sposób:
CAGradientLayer *backgroundLayer = [CAGradientLayer purpleGradientLayer];
backgroundLayer.frame = self.view.frame;
[self.view.layer insertSublayer:backgroundLayer atIndex:0];
viewDidLoad
viewDidLoad
nie działało, jeśli aplikacja została uruchomiona w orientacji poziomej. Moim rozwiązaniem było poszerzenie ramki warstwy tła niż ramki view.frame, aby skompensować inne orientacje.
Ponieważ potrzebowałem tylko jednego rodzaju gradientu w mojej aplikacji, stworzyłem podklasę UIView i wstępnie skonfigurowałem warstwę gradientu przy inicjalizacji za pomocą stałych kolorów. Inicjatory UIView wywołują metodę configureGradientLayer , która konfiguruje 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
jest podobna do inicjalizatora. Nie wydaje mi się, żeby to było odpowiednie.
Szybkie wdrożenie:
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)
Rozszerzyłem nieco przyjętą odpowiedź, używając funkcji rozszerzenia Swift oraz wyliczenia.
No i jeśli używasz Storyboard jak to zrobić, upewnij się, aby zadzwonić gradientBackground(from:to:direction:)
w viewDidLayoutSubviews()
lub później.
Szybki 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)
}
}
Zaimplementowałem to szybko z rozszerzeniem:
Szybki 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)
}
}
Nie, mogę ustawić gradient dla każdego widoku w ten sposób:
myImageView.addGradientWithColor(UIColor.blue)
Szybkie podejście
Ta odpowiedź opiera się na powyższych odpowiedziach i zapewnia implementację rozwiązania problemu niewłaściwego zastosowania gradientu podczas obrotu. Spełnia ten problem, zmieniając warstwę gradientu na kwadrat, dzięki czemu obrót we wszystkich kierunkach daje prawidłowy gradient. Podpis funkcji zawiera argument wariacyjny Swift, który pozwala przekazać tyle CGColorRef (CGColor), ile potrzeba (patrz przykładowe użycie). Podano również przykład rozszerzenia Swift, dzięki czemu można zastosować gradient do dowolnego 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)
}
Używać:
in viewDidLoad ...
override func viewDidLoad() {
super.viewDidLoad()
configureGradientBackground(UIColor.redColor().CGColor, UIColor.whiteColor().CGColor)
}
Implementacja rozszerzenia
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)
}
}
Przykład zastosowania rozszerzenia:
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.configureGradientBackground(UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor, UIColor.whiteColor().CGColor)
}
Co oznacza, że tło gradientowe można teraz zastosować do dowolnego UIControl, ponieważ wszystkie kontrolki są UIViews (lub podklasą), a wszystkie UIViews mają CALayers.
Szybki 4
Implementacja rozszerzenia
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)
}
}
Przykład zastosowania rozszerzenia:
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.configureGradientBackground(UIColor.purple.cgColor, UIColor.blue.cgColor, UIColor.white.cgColor)
}
To czego szukasz CAGradientLayer
. Każda UIView
ma warstwę - do tej warstwy można dodawać podwarstwy, tak jak można dodawać widoki podrzędne. Jednym konkretnym typem jest to CAGradientLayer
, w którym dajesz mu tablicę kolorów do stopniowania.
Jednym z przykładów jest to proste opakowanie dla widoku gradientu:
http://oleb.net/blog/2010/04/obgradientview-a-simple-uiview-wrapper-for-cagradientlayer/
Zauważ, że musisz dołączyć ramę QuartZCore, aby uzyskać dostęp do wszystkich części warstw UIView.
Swift 4:
Prawidłowo pokazuje gradient w 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)
}
}
STOSOWANIE
someView.applyGradient(isVertical: true, colorArray: [.green, .blue])
Prosty szybki widok oparty na wersji 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)
}
}
Następnie możesz użyć gradientLayer po inicjalizacji w ten sposób ...
someView.gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]
Moim rozwiązaniem jest utworzenie UIView
podklasy z CAGradientLayer
dostępną właściwością tylko do odczytu. Umożliwi to dostosowanie gradientu tak, jak chcesz i nie musisz samodzielnie obsługiwać zmian układu. Implementacja podklasy:
@interface GradientView : UIView
@property (nonatomic, readonly) CAGradientLayer *gradientLayer;
@end
@implementation GradientView
+ (Class)layerClass
{
return [CAGradientLayer class];
}
- (CAGradientLayer *)gradientLayer
{
return (CAGradientLayer *)self.layer;
}
@end
Stosowanie:
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);
Dobrze jest zadzwonić do powyższych rozwiązań, aby zaktualizować warstwę w Internecie
viewDidLayoutSubviews
aby poprawnie zaktualizować widoki
SWIFT 3
Aby dodać warstwę gradientu do swojego widoku
Zwiąż swój punkt widokowy
@IBOutlet var YOURVIEW : UIView!
Zdefiniuj CAGradientLayer ()
var gradient = CAGradientLayer()
Oto kod, który musisz napisać w 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)
W Swift 3.1 dodałem to rozszerzenie do 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)
}
}
z którym wtedy dzwonię
class OverviewVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.gradientOfView(withColours: UIColor.red,UIColor.green, UIColor.blue)
}
}
Zaimplementowałem to w moim kodzie.
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];
Teraz widzę gradient w moim widoku.
Aby nadać kolor gradientu UIView (szybki 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
}
Jak używać
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)