在.selected状态下更改自定义UIButton的颜色

时间:2017-10-16 00:07:03

标签: ios swift uibutton

我为应用程序的主屏幕设计了一个径向渐变按钮:

    class RadialGradientButton: UIButton {

    var insideColor: UIColor = ColorScheme.limeGreen
    var outsideColor: UIColor = UIColor.white

    var gradientLocation: CGFloat = 0.9

    override func draw(_ rect: CGRect) {
        let colors = [insideColor.cgColor, outsideColor.cgColor] as CFArray
        let center = CGPoint(x: rect.size.width / 2, y: rect.size.height / 2)

        let endRadius = rect.size.width / 2

        let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: [gradientLocation, 1.0])

        UIGraphicsGetCurrentContext()!.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: endRadius, options: .drawsBeforeStartLocation)
    }

    }

现在使用此按钮我遇到了用户体验问题:当按下按钮时,由于渐变颜色设置,其外观不会以任何方式改变。我希望它的行为与任何系统按钮一样 - 也就是说,insideColor应该在.selected状态下变暗。

setNeedsDisplay()Touch Down事件被触发时,我尝试使用Touch Up Inside,但此方法不会立即重绘,而且可能会对性能造成严重影响。

也许这里有人可以引导我朝着正确的方向前进。

2 个答案:

答案 0 :(得分:3)

首次显示视图或发生使视图的可见部分无效的事件时,将调用

draw()方法。重写此方法,UIKit创建并配置图形上下文,以便在其上绘制和渲染渐变图层。这就是您选择的背景不起作用的原因。

您可以通过在视图上插入两个图层来实现此行为 - 一个用于突出显示,另一个用于正常状态。稍后改变触摸事件的行为。

import UIKit
import QuartzCore


class RoundedButton: UIButton {

var gradientBackgroundLayer : CAGradientLayer?
var selectedLayer : CALayer?

var insideColor: UIColor = UIColor.green;
var outsideColor: UIColor = UIColor.white;
var gradientLocation: NSNumber = 0.9;
let kAnimationLength:CGFloat = 0.15;

override init(frame: CGRect) {
    super.init(frame: frame);
    commonInit();
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder);
    commonInit();
}

override func awakeFromNib() {
    super.awakeFromNib();
    commonInit();
}

func commonInit() {
    self.backgroundColor = nil;
    self.clipsToBounds = true;
    self.setTitleColor(UIColor.white, for: UIControlState.normal)

    let colors : [CGColor] = [insideColor.cgColor, outsideColor.cgColor];
    let locations : [NSNumber] = [0,gradientLocation];

    let layer : CAGradientLayer = CAGradientLayer();
    layer.frame = self.bounds;
    layer.colors = colors;
    layer.locations = locations;

    self.gradientBackgroundLayer = layer;

    let selectedLayer : CALayer = CALayer();
    selectedLayer.frame = self.bounds;
    selectedLayer.backgroundColor = UIColor.lightGray.cgColor
    self.selectedLayer = selectedLayer;
}

func performLayout() {
    self.gradientBackgroundLayer?.frame = self.bounds;
    self.selectedLayer?.frame = self.bounds;

    self.layer.insertSublayer(self.gradientBackgroundLayer!, at: 1);
    self.layer.insertSublayer(self.selectedLayer!, at: 0);

    self.layer.cornerRadius = self.frame.size.height / 2.0;
}

override func layoutSubviews() {
    super.layoutSubviews();
    performLayout();
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event);

    UIView.animate(withDuration: TimeInterval(kAnimationLength), delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations: {
        self.isHighlighted = true;
        self.selectedLayer?.isHidden = false;
        self.gradientBackgroundLayer?.isHidden = true;
    }, completion: nil);
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event);

    UIView.animate(withDuration: TimeInterval(kAnimationLength), delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
        self.isHighlighted = false;
        self.gradientBackgroundLayer?.isHidden = false;
        self.selectedLayer?.isHidden = true;
    }, completion: nil);
}

}

试试这个。希望它能奏效。

答案 1 :(得分:0)

当触摸内部时。

if self.mButton.isSelected = true {
       self.mButton.isSelected = false
       self.mButton.setBackgroundColor(UIColor.red, forState: .normal)
}
else{
       self.mButton.isSelected = true
       self.mButton.setBackgroundColor(UIColor.blue, forState: .normal)
}

您可以在viewDidLoad()

中使用此代码