ios 在 Swift 中的按钮上设置背景渐变

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37903124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:27:25  来源:igfitidea点击:

Set Background Gradient on Button in Swift

iosswiftbuttonlinear-gradients

提问by Michael Yaworski

I have no idea how to set the background gradient on a button (without making the background gradient an image). This is so different from Android.

我不知道如何在按钮上设置背景渐变(不使背景渐变成为图像)。这和安卓有很大的不同。

Here's a class I have to define a returnable gradient scheme:

这是一个我必须定义可返回渐变方案的类:

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

    }
}

I can use this to set the background of my entire view with the following:

我可以使用它来设置整个视图的背景,如下所示:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

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

But how can I access the view of the button and insert the sublayer or something like that?

但是如何访问按钮的视图并插入子图层或类似的东西?

回答by Brandon

Your code works fine. You just have to remember to set the gradient's frame every time. It is better to just make the gradient category also set the frame of the view for you.

你的代码工作正常。你只需要记住每次设置渐变的框架。最好让渐变类别也为您设置视图的框架。

That way you don't forget and it applies fine.

这样你就不会忘记并且它适用。

import UIKit

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

    @discardableResult
    func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> CAGradientLayer {
        let gradient: CAGradientLayer = CAGradientLayer()
        gradient.frame = self.bounds
        gradient.colors = colours.map { 
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(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(with colours: [UIColor], locations: [NSNumber]? = nil) {
        let gradient = CAGradientLayer()
        gradient.frame = self.bounds
        gradient.colors = colours.map { 
import UIKit
class ActualGradientButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }

    private lazy var gradientLayer: CAGradientLayer = {
        let l = CAGradientLayer()
        l.frame = self.bounds
        l.colors = [UIColor.systemYellow.cgColor, UIColor.systemPink.cgColor]
        l.startPoint = CGPoint(x: 0, y: 0.5)
        l.endPoint = CGPoint(x: 1, y: 0.5)
        l.cornerRadius = 16
        layer.insertSublayer(l, at: 0)
        return l
    }()
}
.cgColor } gradient.locations = locations self.layer.insertSublayer(gradient, at: 0) } func applyGradient(with colours: [UIColor], gradient orientation: GradientOrientation) { let gradient = CAGradientLayer() gradient.frame = self.bounds gradient.colors = colours.map {
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(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) {
    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { 
     let button = UIButton(frame: CGRect(x: 60, y: 150, width: 200, height: 60))
    button.setTitle("Email", for: .normal)
    button.backgroundColor = .red
    button.setTitleColor(UIColor.black, for: .normal)
    button.addTarget(self, action: #selector(self.buttonTapped), for: .touchUpInside)

    // Apply Gradient Color
    let gradientLayer:CAGradientLayer = CAGradientLayer()
    gradientLayer.frame.size = button.frame.size
    gradientLayer.colors =
        [UIColor.white.cgColor,UIColor.green.withAlphaComponent(1).cgColor]
    //Use diffrent colors
    button.layer.addSublayer(gradientLayer)
    self.view.addSubview(button)
.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 {
 gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
 gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
.cgColor } gradient.startPoint = orientation.startPoint gradient.endPoint = orientation.endPoint self.layer.insertSublayer(gradient, at: 0) } }
.cgColor } gradient.startPoint = orientation.startPoint gradient.endPoint = orientation.endPoint self.layer.insertSublayer(gradient, at: 0) } }
.cgColor } gradient.locations = locations self.layer.insertSublayer(gradient, at: 0) return gradient } } class ViewController: UIViewController { @IBOutlet weak var btn: UIButton! override func viewDidLoad() { super.viewDidLoad() self.btn.applyGradient(colours: [.yellow, .blue]) self.view.applyGradient(colours: [.yellow, .blue, .red], locations: [0.0, 0.5, 1.0]) } }

Buttons are views. You apply gradients to it the same way you would apply it to any other view.

按钮是视图。您可以将渐变应用于它,就像将它应用于任何其他视图一样。

Picture Proof:enter image description here

图片证明:在此处输入图片说明

Video Proof:https://i.imgur.com/ssDTqPu.mp4

视频证明:https : //i.imgur.com/ssDTqPu.mp4

回答by Zeb

Here below you can find the solution for Swift3(and Swift4too) and a little bit extended (orientation helper):

您可以在下面找到Swift3(以及Swift4)的解决方案和一些扩展(方向助手):

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)

回答by Fattie

It's this simple:

就这么简单:

let gradient: CAGradientLayer = CAGradientLayer()

gradient.colors = [(UIColor(red: 59.0/255.0, green: 187.0/255.0, blue: 182.0/255.0, alpha: 1.00).CGColor), (UIColor(red: 57.0/255.0, green: 174.0/255.0, blue: 236.0/255.0, alpha: 1.00).CGColor)]
gradient.locations = [0.0 , 1.0]

gradient.startPoint = CGPoint(x: 0.0, y: 1.0)
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = CGRect(x: 0.0, y: 0.0, width: btn.frame.size.width, height: btn.frame.size.height)
btn.layer.insertSublayer(gradient, atIndex: 0)

回答by brl214

@Zeb answer is great but just to clean it up and make it a little more swifty. Computed read-only properties should avoid using get and returning Void is redundant:

@Zeb 的回答很棒,但只是为了清理它并使其更加快捷。计算的只读属性应该避免使用 get 并且返回 Void 是多余的:

import Foundation
import UIKit

class GradientButton: UIButton {

    let gradientColors : [UIColor]
    let startPoint : CGPoint
    let endPoint : CGPoint

    required init(gradientColors: [UIColor] = [UIColor.red, UIColor.blue],
                  startPoint: CGPoint = CGPoint(x: 0, y: 0.5),
                  endPoint: CGPoint = CGPoint(x: 1, y: 0.5)) {
        self.gradientColors = gradientColors
        self.startPoint = startPoint
        self.endPoint = endPoint

        super.init(frame: .zero)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let halfOfButtonHeight = layer.frame.height / 2
        contentEdgeInsets = UIEdgeInsets(top: 10, left: halfOfButtonHeight, bottom: 10, right: halfOfButtonHeight)

        layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)

        backgroundColor = UIColor.clear

        // setup gradient

        let gradient = CAGradientLayer()
        gradient.frame = bounds
        gradient.colors = gradientColors.map { 
let button = GradientButton.init(gradientColors:[UIColor.black, UIColor.white], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: 1))
.cgColor } gradient.startPoint = startPoint gradient.endPoint = endPoint gradient.cornerRadius = 4 // replace gradient as needed if let oldGradient = layer.sublayers?[0] as? CAGradientLayer { layer.replaceSublayer(oldGradient, with: gradient) } else { layer.insertSublayer(gradient, below: nil) } // setup shadow layer.shadowColor = UIColor.darkGray.cgColor layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: halfOfButtonHeight).cgPath layer.shadowOffset = CGSize(width: 0.0, height: 1.0) layer.shadowOpacity = 0.85 layer.shadowRadius = 4.0 } override var isHighlighted: Bool { didSet { let newOpacity : Float = isHighlighted ? 0.6 : 0.85 let newRadius : CGFloat = isHighlighted ? 6.0 : 4.0 let shadowOpacityAnimation = CABasicAnimation() shadowOpacityAnimation.keyPath = "shadowOpacity" shadowOpacityAnimation.fromValue = layer.shadowOpacity shadowOpacityAnimation.toValue = newOpacity shadowOpacityAnimation.duration = 0.1 let shadowRadiusAnimation = CABasicAnimation() shadowRadiusAnimation.keyPath = "shadowRadius" shadowRadiusAnimation.fromValue = layer.shadowRadius shadowRadiusAnimation.toValue = newRadius shadowRadiusAnimation.duration = 0.1 layer.add(shadowOpacityAnimation, forKey: "shadowOpacity") layer.add(shadowRadiusAnimation, forKey: "shadowRadius") layer.shadowOpacity = newOpacity layer.shadowRadius = newRadius let xScale : CGFloat = isHighlighted ? 1.025 : 1.0 let yScale : CGFloat = isHighlighted ? 1.05 : 1.0 UIView.animate(withDuration: 0.1) { let transformation = CGAffineTransform(scaleX: xScale, y: yScale) self.transform = transformation } } } }

回答by Jaywant Khedkar

Try this is working for me ,

试试这对我有用,

     @IBOutlet weak var btnCenter: UIButton!
     @IBOutlet weak var viewCenter: UIView!

    // Create a gradient layer
    let gradient = CAGradientLayer()

    // gradient colors in order which they will visually appear
    gradient.colors = [UIColor.yello.cgColor, UIColor.blue.cgColor]

    // Gradient from left to right
    gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradient.endPoint = CGPoint(x: 1.0, y: 0.5)

    // set the gradient layer to the same size as the view
    gradient.frame = viewCenter.bounds

    // add the gradient layer to the views layer for rendering
    viewCenter.layer.insertSublayer(gradient, at: 0)

    // Tha magic! Set the button as the views mask
    viewCenter.mask = btnCenter

    //Set corner Radius and border Width of button
    btnCenter.layer.cornerRadius =  btnCenter.frame.size.height / 2
    btnCenter.layer.borderWidth = 5.0

enter image description here

在此处输入图片说明

You can add starting and end point of gradient color.

您可以添加渐变颜色的起点和终点。

   class ButtonGradient : UIButton {
        override func layoutSubviews() {

            let layer : CAGradientLayer = CAGradientLayer()
            layer.frame.size = self.frame.size
            layer.frame.origin = CGPoint(x: 0, y: 0)

            //   layer.cornerRadius = CGFloat(frame.width / 20)
            let color0 = UIColor(red:255/255, green:122/255, blue:0/255, alpha:1.0).cgColor
            let color1 = UIColor(red:255/255, green:176/255, blue: 0/255, alpha:1.0).cgColor
            let color2 = UIColor(red:250/255, green:98/255, blue: 44/255, alpha:1.0).cgColor
            layer.locations = [0.5, 1.0]
            layer.startPoint = CGPoint(x: 0.0, y: 0.5)
            layer.endPoint = CGPoint(x: 0.5, y: 0.5)
            layer.colors = [color2,color0,color1]

            self.layer.insertSublayer(layer, at: 0)
        }
    }

enter image description here

在此处输入图片说明

For more details description refer CAGradientLayer doc

有关更多详细说明,请参阅CAGradientLayer 文档

回答by Alper

I have tried all of them this is my button init inside of viewdidload

我已经尝试了所有这些,这是我在 viewdidload 中的按钮初始化

##代码##

anchor is an extension, so this is irrelevant gradient.

锚是一个扩展,所以这是不相关的梯度。

回答by Hardik Thakkar

For Swift 2.0 to give gradients color to UIButton

Swift 2.0 为 UIButton 提供渐变颜色

##代码##

回答by Ngima Sherpa

There are already many answers there I want add what I did to achieve this. I use this custom Button GradientButton

那里已经有很多答案,我想添加我为实现这一目标所做的工作。我使用这个自定义按钮 GradientButton

##代码##

You can make GradientButton instance like this.

您可以像这样制作 GradientButton 实例。

##代码##

回答by Merry

Here, I have taken one UIView and add button in it.

在这里,我采用了一个 UIView 并在其中添加了按钮。

##代码##

enter image description here

在此处输入图片说明

回答by Deviyani Swami

enter image description here

在此处输入图片说明

##代码##

After that directly assign "ButtonGredient" class to particular button in Storyboard.

之后直接将“ButtonGredient”类分配给故事板中的特定按钮。