簡體   English   中英

自定義UIButton的邊緣與之交互后看起來像是像素化

[英]Custom UIButton's edges look pixelated after interacting with it

我創建了一個帶有圓角,漸變背景和陰影的自定義UIButton子類。 啟動應用程序后,按鈕看起來可以正常顯示並進行抗鋸齒處理,但是如果我按下按鈕,其邊緣將變得像素化。

我已經嘗試了很多方法,例如在按鈕的圖層上設置.allowsEdgeAntialiasing = true或從“突出顯示”的設置器中刪除比例轉換動畫等,根本沒有任何幫助:(

這是我的按鈕類:

@IBDesignable class CircleTintedButton: UIButton {
    @IBInspectable var cornerRadius : CGFloat = 1.0
    @IBInspectable var shadowOffsetWidth: CGFloat = 0.0
    @IBInspectable var shadowOffsetHeight: CGFloat = 2.0
    @IBInspectable var shadowColor : UIColor = UIColor.gray
    @IBInspectable var shadowOpacity: CGFloat = 0.3

    @IBInspectable var startColor: UIColor = .blue {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var endColor: UIColor = .green {
        didSet {
            setNeedsLayout()
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        layer.cornerRadius = cornerRadius
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOffset = CGSize(width: shadowOffsetWidth, height: shadowOffsetHeight)
        let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
        layer.shadowPath = shadowPath.cgPath
        layer.shadowOpacity = Float(shadowOpacity)

        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]        
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.6)

        gradientLayer.locations = [0, 1]
        gradientLayer.frame = bounds
        gradientLayer.cornerRadius = cornerRadius
        gradientLayer.masksToBounds = true

        layer.insertSublayer(gradientLayer, below: self.titleLabel?.layer)        
    }

    override var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            let xScale : CGFloat = newValue ? 1.025 : 1.0
            let yScale : CGFloat = newValue ? 1.1 : 1.0
            UIView.animate(withDuration: 0.1) {
                let transformation = CGAffineTransform(scaleX: xScale, y: yScale)
                self.transform = transformation
            }

            super.isHighlighted = newValue
        }
    }
}

我的測試設備(iPhone 7 @ 12.1.2)的一些屏幕截圖:

應用啟動后: https : //vinishko.party/files/ok.jpg

按此按鈕后: https : //vinishko.party/files/aliased.jpg

已經花了整整一天的時間試圖解決這個問題,請幫助我:D謝謝。

每次調用layoutSubviews()都要添加另一個漸變層。 您可以通過為按鈕添加@IBAction來確認這一點:

@IBAction func didTap(_ sender: Any) {

    if let b  = sender as? CircleTintedButton {
        let n = b.layer.sublayers?.count
        print("nunLayers: \(String(describing: n))")
    }

}

您會看到子層數隨着每次點擊而增加。

將漸變圖層添加為自定義按鈕的var /屬性,然后僅將其添加一次:

@IBDesignable class CircleTintedButton: UIButton {
    @IBInspectable var cornerRadius : CGFloat = 1.0
    @IBInspectable var shadowOffsetWidth: CGFloat = 0.0
    @IBInspectable var shadowOffsetHeight: CGFloat = 2.0
    @IBInspectable var shadowColor : UIColor = UIColor.gray
    @IBInspectable var shadowOpacity: CGFloat = 0.3

    // add this var / property
    private var gradLayer: CAGradientLayer?

    @IBInspectable var startColor: UIColor = .blue {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var endColor: UIColor = .green {
        didSet {
            setNeedsLayout()
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        layer.cornerRadius = cornerRadius
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOffset = CGSize(width: shadowOffsetWidth, height: shadowOffsetHeight)
        let shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
        layer.shadowPath = shadowPath.cgPath
        layer.shadowOpacity = Float(shadowOpacity)

        // only create / add the gradient layer once
        if gradLayer == nil {

            let gradientLayer = CAGradientLayer()

            gradientLayer.locations = [0, 1]
            gradientLayer.masksToBounds = true

            layer.insertSublayer(gradientLayer, below: self.titleLabel?.layer)

            self.gradLayer = gradientLayer

        }

        gradLayer?.colors = [startColor.cgColor, endColor.cgColor]
        gradLayer?.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradLayer?.endPoint = CGPoint(x: 1.0, y: 0.6)

        gradLayer?.frame = bounds
        gradLayer?.cornerRadius = cornerRadius

// original code
//      let gradientLayer = CAGradientLayer()
//      gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
//      gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
//      gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.6)
//
//      gradientLayer.locations = [0, 1]
//      gradientLayer.frame = bounds
//      gradientLayer.cornerRadius = cornerRadius
//      gradientLayer.masksToBounds = true
//
//      layer.insertSublayer(gradientLayer, below: self.titleLabel?.layer)
    }

    override var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            let xScale : CGFloat = newValue ? 1.025 : 1.0
            let yScale : CGFloat = newValue ? 1.1 : 1.0
            UIView.animate(withDuration: 0.1) {
                let transformation = CGAffineTransform(scaleX: xScale, y: yScale)
                self.transform = transformation
            }

            super.isHighlighted = newValue
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM