2016-06-19 3 views
9

Я понятия не имею, как установить фоновый градиент на кнопку (без создания фонового градиента изображения). Это сильно отличается от Android.Установите фона градиента на кнопке в Swift

Вот класс я должен определить возвратную схему градиента:

import UIKit 

extension CAGradientLayer { 

    func backgroundGradientColor() -> CAGradientLayer { 
     let topColor = UIColor(red: (0/255.0), green: (153/255.0), blue:(51/255.0), alpha: 1) 
     let bottomColor = UIColor(red: (0/255.0), green: (153/255.0), blue:(255/255.0), alpha: 1) 

     let gradientColors: [CGColor] = [topColor.CGColor, bottomColor.CGColor] 
     let gradientLocations: [Float] = [0.0, 1.0] 

     let gradientLayer: CAGradientLayer = CAGradientLayer() 
     gradientLayer.colors = gradientColors 
     gradientLayer.locations = gradientLocations 

     return gradientLayer 

    } 
} 

я могу использовать это, чтобы установить фон всей моей точки зрения следующим:

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let background = CAGradientLayer().backgroundGradientColor() 
     background.frame = self.view.bounds 
     self.view.layer.insertSublayer(background, atIndex: 0) 
    } 
    //... 
} 

Но как я могу получить доступ к представлению кнопки и вставить подслой или что-то в этом роде? Я пару раз зашел в Google и не нашел ничего полезного. Я довольно потерял это.

ответ

24

Ваш код работает нормально. Вам просто нужно помнить, чтобы каждый раз устанавливать рамку градиента. Лучше просто сделать категорию градиента также заданной для вас рамкой представления.

Таким образом, вы не забываете, и оно применяется отлично.

extension UIView { 
    func applyGradient(colours: [UIColor]) -> Void { 
     self.applyGradient(colours, locations: nil) 
    } 

    func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void { 
     let gradient: CAGradientLayer = CAGradientLayer() 
     gradient.frame = self.bounds 
     gradient.colors = colours.map { $0.CGColor } 
     gradient.locations = locations 
     self.layer.insertSublayer(gradient, atIndex: 0) 
    } 
} 

class ViewController: UIViewController { 

    @IBOutlet weak var btn: UIButton! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.btn.titleLabel?.textColor = UIColor.whiteColor() 

     self.btn.applyGradient([UIColor.yellowColor(), UIColor.blueColor()]) 
     self.view.applyGradient([UIColor.yellowColor(), UIColor.blueColor(), UIColor.redColor()], locations: [0.0, 0.5, 1.0]) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 
} 

Кнопки - это виды. Вы применяете к нему градиенты так же, как и к любому другому представлению.

+3

Я не согласен с последним предложением. В то время как кнопки являются видами, фон кнопки не совпадает с фоном представления. Фон кнопки может меняться в зависимости от состояния кнопки. При добавлении градиента в качестве слоя мы теряем этот эффект. Идеальное решение состоит в том, чтобы захватить слой градиента в изображение, задав изображение как фоновое изображение кнопки. Другая проблема заключается в том, что границы слоев должны обновляться всегда, когда изменяется рамка кнопки, то есть из 'layoutSubviews'. – Sulthan

8

Здесь ниже вы можете найти решение для Swift3 и немного расширенной (помощник ориентации):

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint) 

enum GradientOrientation { 
    case topRightBottomLeft 
    case topLeftBottomRight 
    case horizontal 
    case vertical 

    var startPoint : CGPoint { 
    return points.startPoint 
    } 

    var endPoint : CGPoint { 
    return points.endPoint 
    } 

    var points : GradientPoints { 
    get { 
     switch(self) { 
     case .topRightBottomLeft: 
     return (CGPoint(x: 0.0,y: 1.0), CGPoint(x: 1.0,y: 0.0)) 
     case .topLeftBottomRight: 
     return (CGPoint(x: 0.0,y: 0.0), CGPoint(x: 1,y: 1)) 
     case .horizontal: 
     return (CGPoint(x: 0.0,y: 0.5), CGPoint(x: 1.0,y: 0.5)) 
     case .vertical: 
     return (CGPoint(x: 0.0,y: 0.0), CGPoint(x: 0.0,y: 1.0)) 
     } 
    } 
    } 
} 

extension UIView { 

    func applyGradient(withColours colours: [UIColor], locations: [NSNumber]? = nil) -> Void { 
    let gradient = CAGradientLayer() 
    gradient.frame = self.bounds 
    gradient.colors = colours.map { $0.cgColor } 
    gradient.locations = locations 
    self.layer.insertSublayer(gradient, at: 0) 
    } 

    func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) -> Void { 
    let gradient = CAGradientLayer() 
    gradient.frame = self.bounds 
    gradient.colors = colours.map { $0.cgColor } 
    gradient.startPoint = orientation.startPoint 
    gradient.endPoint = orientation.endPoint 
    self.layer.insertSublayer(gradient, at: 0) 
    } 
} 
3

@Zeb ответ отлично, но только, чтобы очистить его и сделать его немного более Swifty , вычисляемые свойства только для чтения следует избегать использования Досталось и возвращения Пустота является избыточным:

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint) 

enum GradientOrientation { 
    case topRightBottomLeft 
    case topLeftBottomRight 
    case horizontal 
    case vertical 

var startPoint: CGPoint { 
    return points.startPoint 
} 

var endPoint: CGPoint { 
    return points.endPoint 
} 

var points: GradientPoints { 
    switch self { 
    case .topRightBottomLeft: 
     return (CGPoint.init(x: 0.0, y: 1.0), CGPoint.init(x: 1.0, y: 0.0)) 
    case .topLeftBottomRight: 
     return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 1, y: 1)) 
    case .horizontal: 
     return (CGPoint.init(x: 0.0, y: 0.5), CGPoint.init(x: 1.0, y: 0.5)) 
    case .vertical: 
     return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 0.0, y: 1.0)) 
    } 
    } 
} 

extension UIView { 

func applyGradient(withColours colours: [UIColor], locations: [NSNumber]? = nil) { 
    let gradient: CAGradientLayer = CAGradientLayer() 
    gradient.frame = self.bounds 
    gradient.colors = colours.map { $0.cgColor } 
    gradient.locations = locations 
    self.layer.insertSublayer(gradient, at: 0) 
} 

func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) { 
    let gradient: CAGradientLayer = CAGradientLayer() 
    gradient.frame = self.bounds 
    gradient.colors = colours.map { $0.cgColor } 
    gradient.startPoint = orientation.startPoint 
    gradient.endPoint = orientation.endPoint 
    self.layer.insertSublayer(gradient, at: 0) 
    } 
} 
+0

Это прекрасно работает, я попытался установить UIButton cornerRadius, но его не получило никакого эффекта, если я не удалю градиент, есть ли способ решить это? – SimpiMind

+0

Попробовал ли вы установить маски_ToBounds = false – brl214

1

Я попробовал все из них это моя кнопка инициализации внутри viewdidload

let button = UIButton() 
    button.setTitle("Alper", for: .normal) 
    button.layer.borderColor = UIColor.white.cgColor 
    button.layer.borderWidth = 1 
    view.addSubview(button) 
    button.anchor(top: nil, left: nil, bottom: logo.topAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, height: 50, width: 100) 
    let gradientx = CAGradientLayer() 
    gradientx.colors = [UIColor.blue,UIColor.red] 
    gradientx.startPoint = CGPoint(x: 0.0, y: 0.5) 
    gradientx.endPoint = CGPoint(x: 1.0, y: 1.0) 
    gradientx.frame = button.bounds 
    button.layer.insertSublayer(gradientx, at: 0) 

анкер является продолжением, так это неуместный градиент.

Смежные вопросы