2016-06-19 24 views
9

Nie mam pojęcia, jak ustawić gradient tła na przycisku (bez wykonywania gradientu tła obrazu). To bardzo różni się od Androida.Ustaw Gradient tła na przycisku w Swift

Oto klasa muszę zdefiniować zwrotnej schemat gradient:

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 

    } 
} 

mogę to wykorzystać, aby ustawić tło całym moim zdaniem z następujących czynności:

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

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

ale jak mogę uzyskać dostęp do widoku przycisku i wstawić podwarstwa lub coś w tym stylu? Mam Google przez kilka godzin i nie mogę znaleźć niczego przydatnego. Jestem z tego całkiem zgubiony.

Odpowiedz

24

Twój kod działa poprawnie. Trzeba tylko pamiętać, aby za każdym razem ustawić ramkę gradientu. Lepiej jest po prostu, aby kategoria gradientu również ustawiła ramkę widoku dla ciebie.

W ten sposób nie zapomnisz i będzie to miało zastosowanie.

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

Przyciski to widoki. Stosujesz gradienty w taki sam sposób, w jaki zastosowałbyś go do dowolnego innego widoku.

+3

Nie zgadzam się z ostatnim zdaniem. Podczas gdy przyciski są widokami, tło przycisku nie jest tym samym, co tło widoku. Tło przycisków może się zmieniać w zależności od stanu przycisku. Dodając gradient jako warstwę, tracimy ten efekt. Idealnym rozwiązaniem jest przechwycenie warstwy gradientu w obraz i ustawienie obrazu jako obrazu tła przycisku. Innym problemem jest to, że krawędzie warstw powinny być aktualizowane zawsze, gdy zmienia się ramka przycisku, czyli z "layoutSubviews". – Sulthan

8

Tutaj poniżej można znaleźć rozwiązanie dla Swift3 i nieco rozszerzony (orientacja pomocnika):

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 odpowiedź jest wielki, ale po prostu go oczyścić i uczynić go trochę bardziej swifty . Obliczone właściwości tylko do odczytu należy unikać GET i powrocie Pustka jest zbędna:

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

Działa to dobrze, próbowałem ustawić UIButton cornerRadius, ale nie przynosi żadnego efektu, chyba że usunąć gradient, czy istnieje sposób, aby rozwiązać ten problem? – SimpiMind

+0

Czy próbowałeś ustawić masksToBounds = false – brl214

1

Próbowałem wszystkie z nich to mój przycisk startowych wewnątrz 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) 

kotwica jest rozszerzeniem, więc to nieistotny gradient.