ios - 为什么 UIButton 不显示渐变
问题描述
嗨,我是 Swift 和 Xcode 的新手,只是学习基础知识。我以编程方式添加了一个渐变层,然后UIButton
使用主故事板添加了一个并为其分配了一个出口,但是当我运行代码时,渐变层显示但按钮显示,但是,当我删除渐变层时,UIButton
显示。附件是同时使用渐变和代码时发生的情况的屏幕截图,并且将附加 a。
class ViewController: UIViewController {
let layer = CAGradientLayer()
@IBOutlet weak var pressMeButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
layer.frame = view.bounds
layer.colors = [UIColor.white.cgColor, UIColor(red: 128/255, green: 206/255, blue: 255/255, alpha: 1).cgColor]
layer.startPoint = CGPoint(x: 0, y: 0)
layer.endPoint = CGPoint(x: 0, y: 0.4)
view.layer.addSublayer(layer)
pressMeButton.layer.cornerRadius = 25.0
pressMeButton.layer.borderWidth = 0.8
pressMeButton.layer.borderColor = UIColor.black.cgColor
pressMeButton.setTitle("Press Me", for: .normal)
pressMeButton.setTitleColor(.black, for: .normal)
}
}
带有故事板的代码显示按钮放置和没有按钮的模拟器:
解决方案
主要问题是渐变层放置在按钮的顶部。第二个问题(你还没有提到)是如果你旋转设备,它不会响应框架中的变化。
最好的解决方案是定义一个GradientView
由它决定的支持层layerClass
是一个CAGradientLayer
。这样(a)它将始终位于按钮下方;并且 (b) 它会自动适应变化(并且在动画期间也会比或接近时frame
更优雅地这样做):layoutSubviews
viewDidLayoutSubviews
@IBDesignable
class GradientView: UIView {
override class var layerClass: AnyClass { return CAGradientLayer.self }
private var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer }
@IBInspectable var startColor: UIColor = .white { didSet { updateGradient() } }
@IBInspectable var endColor: UIColor = #colorLiteral(red: 0.5019607843, green: 0.8078431373, blue: 1, alpha: 1) { didSet { updateGradient() } }
@IBInspectable var startPoint: CGFloat = 0 { didSet { updateGradient() } }
@IBInspectable var endPoint: CGFloat = 0.4 { didSet { updateGradient() } }
override init(frame: CGRect = .zero) {
super.init(frame: frame)
updateGradient()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
updateGradient()
}
}
private extension GradientView {
func updateGradient() {
gradientLayer.colors = [startColor, endColor].map { $0.cgColor }
gradientLayer.startPoint = CGPoint(x: 0, y: startPoint)
gradientLayer.endPoint = CGPoint(x: 0, y: endPoint)
}
}
使用这个@IBDesignable
类,您可以将视图控制器的视图的基类设置为GradientView
,它将呈现在按钮下方,并正确显示在 Interface Builder 中。例如,单击背景视图并转到最右侧面板中的“Identity Inspector”选项卡,并在“Custom Class”部分设置“Class”:
如果需要,您可以在 IB 中更改开始/结束颜色和开始/结束点,方法是选择右侧的“属性检查器”面板:
显然,如果您这样做,那么您根本不必在视图层中玩耍viewDidLoad
。但是,如果您想以编程方式更改它,您可以执行以下操作:
override func viewDidLoad() {
super.viewDidLoad()
if let view = view as? GradientView {
view.startColor = .black
view.endColor = .red
}
}
但我个人会在 IB 中正确设置颜色(或其他)。而且我会将所有“视图配置”代码保留UIView
在它所属的类中,而不是在视图控制器中。
推荐阅读
- python - 如何使用不匹配的维度进行矢量化
- firebase - 如何使用 Google OAuth 2.0 获取带有刷新令牌的新访问令牌?
- c++ - 许多慢核心没有加速?
- arrays - PowerShell 如何将 Get-ChildItem 输出转换为字符串数组
- ssl-certificate - 为亚马逊 lightsail 使用 SSL
- python - 如何以编程方式检查python包是否是最新版本?
- shopify - 在特定位置的产品页面上显示变体价格
- java - Jenkins插件:发送FormValidation.error()时如何停用作业保存按钮?
- javascript - 仅在有历史记录时显示按钮
- python - 运行预提交运行时出错