【问题标题】:why does UIButton not show with gradient为什么 UIButton 不显示渐变
【发布时间】:2020-07-25 09:37:16
【问题描述】:

您好,我是 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)
    }
}

带有故事板的代码显示按钮放置和没有按钮的模拟器:

【问题讨论】:

    标签: ios swift xcode storyboard ios-simulator


    【解决方案1】:

    您在视图顶部添加图层,而您之前添加了 UIButton。所以图层与 UIButton 重叠。

    您需要在控制器的主视图中添加一个容器视图,然后在其上添加渐变层。

    【讨论】:

    • 我该怎么做?
    【解决方案2】:

    主要问题是渐变层放置在按钮的顶部。第二个问题(您还没有提到)是,如果您旋转设备,它不会响应框架中的变化。

    最好的解决方案是定义一个GradientView,其支持层由layerClass 决定,是CAGradientLayer。这样(a)它将始终位于按钮下方;并且 (b) 它将自动适应 frame 的变化(并且在动画期间会比 layoutSubviewsviewDidLayoutSubviews 更优雅地进行调整):

    @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 中更改开始/结束颜色和开始/结束点,方法是选择右侧的“Attributes Inspector”面板:

    显然,如果您这样做,那么您根本不必在viewDidLoad 中使用视图层。但是,如果您想以编程方式更改它,您可以执行以下操作:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if let view = view as? GradientView {
            view.startColor = .black
            view.endColor = .red
        }
    }
    

    但我个人会在 IB 中正确设置颜色(或其他)。我会将所有“视图配置”代码保留在它所属的 UIView 类中,而不是在视图控制器中。

    【讨论】:

      【解决方案3】:

      感谢所有帮助,但最终我创建了一个带有参数的玻璃来做渐变,另一个玻璃带有某些颜色的参数,然后能够将它们拉入 viewLoad。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-16
        相关资源
        最近更新 更多