1. ホーム
  2. ios

[解決済み] Swift - コーナーラジアスとドロップシャドウの問題

2023-02-01 15:15:44

質問

ボタンを作成しようとしています。 丸みを帯びた角 ドロップシャドウ . どのように切り替えても、ボタンが正しく表示されません。試したのは masksToBounds = falsemasksToBounds = true のように表示されますが、コーナー半径が機能してシャドウが機能しないか、シャドウが機能してコーナー半径がボタンの角を切り取らないかのどちらかです。

import UIKit
import QuartzCore

@IBDesignable
class Button : UIButton
{
    @IBInspectable var masksToBounds: Bool    = false                {didSet{updateLayerProperties()}}
    @IBInspectable var cornerRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var borderWidth  : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var borderColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}
    @IBInspectable var shadowColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}
    @IBInspectable var shadowOpacity: CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var shadowRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}
    @IBInspectable var shadowOffset : CGSize  = CGSizeMake(0, 0)     {didSet{updateLayerProperties()}}

    override func drawRect(rect: CGRect)
    {
        updateLayerProperties()
    }

    func updateLayerProperties()
    {
        self.layer.masksToBounds = masksToBounds
        self.layer.cornerRadius = cornerRadius
        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.CGColor
        self.layer.shadowColor = shadowColor.CGColor
        self.layer.shadowOpacity = CFloat(shadowOpacity)
        self.layer.shadowRadius = shadowRadius
        self.layer.shadowOffset = shadowOffset
    }
}

どのように解決するのですか?

次の Swift 5 / iOS 12 のコードでは、サブクラスの UIButton のサブクラスを設定する方法を示しています。これにより、角を丸くしたインスタンスとその周りの影を作成することができます。

import UIKit

final class CustomButton: UIButton {

    private var shadowLayer: CAShapeLayer!

    override func layoutSubviews() {
        super.layoutSubviews()

        if shadowLayer == nil {
            shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath
            shadowLayer.fillColor = UIColor.white.cgColor

            shadowLayer.shadowColor = UIColor.darkGray.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 2.0, height: 2.0)
            shadowLayer.shadowOpacity = 0.8
            shadowLayer.shadowRadius = 2

            layer.insertSublayer(shadowLayer, at: 0)
            //layer.insertSublayer(shadowLayer, below: nil) // also works
        }        
    }

}

あなたのニーズに応じて UIButton を追加し、そのクラスを CustomButton のインスタンスを作成するか、あるいは CustomButton のインスタンスをプログラム的に作成することもできます。次のような UIViewController を作成し、使用する方法を示しています。 CustomButton のインスタンスを作成し、使用する方法を示します。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(type: .system)
        button.setTitle("Button", for: .normal)
        view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)        
        let widthConstraint = button.widthAnchor.constraint(equalToConstant: 100)
        let heightConstraint = button.heightAnchor.constraint(equalToConstant: 100)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
    }

}


先ほどのコードで、iPhoneシミュレータでは以下のような画像が表示されます。