2016-06-19 18 views
9

Ich habe keine Ahnung, wie man den Hintergrundgradienten auf einer Schaltfläche einstellt (ohne den Hintergrundfarbverlauf zu einem Bild zu machen). Das ist so anders als bei Android.Hintergrundfarbe auf Knopf in Swift setzen

hier eine Klasse ist Ich habe ein Mehrweg-Gradientenschema zu definieren:

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 

    } 
} 

ich dies den Hintergrund meiner gesamten Ansicht mit dem folgenden festlegen kann:

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

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

Aber wie kann ich Zugriff auf die Ansicht der Schaltfläche und fügen Sie die Sublayer oder etwas ähnliches ein? Ich habe ein paar Stunden gegoogelt und kann nichts hilfreiches finden. Ich bin ziemlich verloren damit.

Antwort

24

Ihr Code funktioniert gut. Sie müssen nur daran denken, den Rahmen des Farbverlaufs jedes Mal zu setzen. Es ist besser, wenn Sie nur die Gradient-Kategorie festlegen, die den Rahmen der Ansicht für Sie festlegt.

So vergessen Sie nicht, und es gilt gut.

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

Schaltflächen sind Ansichten. Sie wenden Gradienten auf dieselbe Weise an, wie Sie sie auf eine andere Ansicht anwenden würden.

+3

Ich stimme dem letzten Satz nicht zu. Während Schaltflächen Ansichten sind, ist der Hintergrund der Schaltfläche nicht identisch mit dem Hintergrund der Ansicht. Der Schaltflächenhintergrund kann sich je nach Status der Schaltfläche ändern. Wenn wir den Verlauf als Ebene hinzufügen, verlieren wir diesen Effekt. Die ideale Lösung besteht darin, die Farbverlaufsebene in ein Bild einzufügen und das Bild als Hintergrundbild für die Schaltfläche festzulegen. Ein weiteres Problem ist, dass die Ebenengrenzen immer aktualisiert werden sollen, wenn sich der Schaltflächenrahmen ändert, also von 'layoutSubviews'. – Sulthan

8

Hier unten Sie die Lösung für swift3 und ein wenig erweitert (Orientierung Helfer) finden:

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 Antwort ist groß, aber nur um es zu reinigen und macht es ein wenig mehr swifty . Computed Nur-Lese-Eigenschaften sollten mit get vermeiden und die Rückkehr Void ist redundant:

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

Das funktioniert gut, ich habe versucht, UIButton CornerRadius zu setzen, aber es wird keine Wirkung, wenn ich Gradienten entfernen, gibt es eine Möglichkeit, dies zu lösen? – SimpiMind

+0

Haben Sie versucht, masksToBounds = false zu setzen? – brl214

1

ich versucht habe, alle von ihnen dies ist meine Schaltfläche init innerhalb von 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) 

Anker eine Erweiterung ist, so das ist irrelevanter Gradient.