簡體   English   中英

向我的 UIView 添加陰影的最佳方法是什么

[英]What's the best way to add a drop shadow to my UIView

我正在嘗試為相互疊加的視圖添加陰影,視圖折疊允許看到其他視圖中的內容,在這種情況下,我想保持view.clipsToBounds ON,以便當視圖折疊其內容時被剪輯。

這似乎讓我很難在圖層中添加陰影,因為當我打開clipsToBounds ,陰影也會被剪裁。

我一直在嘗試操作view.frameview.bounds以向框架添加陰影,但允許邊界足夠大以包含它,但是我對此沒有運氣。

這是我用來添加陰影的代碼(這只適用於clipsToBounds OFF,如圖所示)

view.clipsToBounds = NO;
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowOffset = CGSizeMake(0,5);
view.layer.shadowOpacity = 0.5;

這是應用於最淺灰色層的陰影的屏幕截圖。 希望這可以讓我了解如果clipsToBounds關閉,我的內容將如何重疊。

影子應用程序。

如何為我的UIView添加陰影並保持我的內容被剪裁?

編輯:只是想補充一點,我也使用過帶陰影的背景圖像,效果很好,但是我仍然想知道最好的編碼解決方案。

嘗試這個:

UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:view.bounds];
view.layer.masksToBounds = NO;
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
view.layer.shadowOpacity = 0.5f;
view.layer.shadowPath = shadowPath.CGPath;

首先:在UIBezierPath作為shadowPath是至關重要的。 如果您不使用它,一開始您可能不會注意到差異,但敏銳的眼睛會觀察到在旋轉設備和/或類似事件期間發生的一定滯后。 這是一個重要的性能調整。

具體關於您的問題:重要的一行是view.layer.masksToBounds = NO 它禁用了超出視圖邊界的視圖層子層的裁剪。

對於那些想知道masksToBounds (在圖層上)和視圖自己的clipToBounds屬性之間有什么區別的人來說:實際上沒有任何clipToBounds 切換一個會對另一個產生影響。 只是抽象層次不同。


斯威夫特 2.2:

override func layoutSubviews()
{
    super.layoutSubviews()

    let shadowPath = UIBezierPath(rect: bounds)
    layer.masksToBounds = false
    layer.shadowColor = UIColor.blackColor().CGColor
    layer.shadowOffset = CGSizeMake(0.0, 5.0)
    layer.shadowOpacity = 0.5
    layer.shadowPath = shadowPath.CGPath
}

斯威夫特 3:

override func layoutSubviews()
{
    super.layoutSubviews()

    let shadowPath = UIBezierPath(rect: bounds)
    layer.masksToBounds = false
    layer.shadowColor = UIColor.black.cgColor
    layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
    layer.shadowOpacity = 0.5
    layer.shadowPath = shadowPath.cgPath
}

Wasabii 在 Swift 2.3 中的回答:

let shadowPath = UIBezierPath(rect: view.bounds)
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.blackColor().CGColor
view.layer.shadowOffset = CGSize(width: 0, height: 0.5)
view.layer.shadowOpacity = 0.2
view.layer.shadowPath = shadowPath.CGPath

在 Swift 3/4/5 中:

let shadowPath = UIBezierPath(rect: view.bounds)
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: 0.5)
view.layer.shadowOpacity = 0.2
view.layer.shadowPath = shadowPath.cgPath

如果您使用 AutoLayout,請將此代碼放在 layoutSubviews() 中。

在 SwiftUI 中,這一切都容易得多:

Color.yellow  // or whatever your view
    .shadow(radius: 3)
    .frame(width: 200, height: 100)

您可以為 UIView 創建擴展以在設計編輯器中訪問這些值

設計編輯器中的陰影選項

extension UIView{

    @IBInspectable var shadowOffset: CGSize{
        get{
            return self.layer.shadowOffset
        }
        set{
            self.layer.shadowOffset = newValue
        }
    }

    @IBInspectable var shadowColor: UIColor{
        get{
            return UIColor(cgColor: self.layer.shadowColor!)
        }
        set{
            self.layer.shadowColor = newValue.cgColor
        }
    }

    @IBInspectable var shadowRadius: CGFloat{
        get{
            return self.layer.shadowRadius
        }
        set{
            self.layer.shadowRadius = newValue
        }
    }

    @IBInspectable var shadowOpacity: Float{
        get{
            return self.layer.shadowOpacity
        }
        set{
            self.layer.shadowOpacity = newValue
        }
    }
}

訣竅是正確定義視圖層的masksToBounds屬性:

view.layer.masksToBounds = NO;

它應該工作。

來源

您也可以從故事板為您的視圖設置陰影

在此處輸入圖片說明

在 viewWillLayoutSubviews 上:

override func viewWillLayoutSubviews() {
    sampleView.layer.masksToBounds =  false
    sampleView.layer.shadowColor = UIColor.darkGrayColor().CGColor;
    sampleView.layer.shadowOffset = CGSizeMake(2.0, 2.0)
    sampleView.layer.shadowOpacity = 1.0
}

使用 UIView 的擴展:

extension UIView {

    func addDropShadowToView(targetView:UIView? ){
        targetView!.layer.masksToBounds =  false
        targetView!.layer.shadowColor = UIColor.darkGrayColor().CGColor;
        targetView!.layer.shadowOffset = CGSizeMake(2.0, 2.0)
        targetView!.layer.shadowOpacity = 1.0
    }
}

用法:

sampleView.addDropShadowToView(sampleView)

所以是的,您應該更喜歡 shadowPath 屬性以提高性能,而且:來自 CALayer.shadowPath 的頭文件

使用此屬性顯式指定路徑通常會 * 提高渲染性能,因為將共享相同的路徑 * 跨多個層引用

一個鮮為人知的技巧是跨多個層共享相同的參考。 當然,它們必須使用相同的形狀,但這在表格/集合視圖單元格中很常見。

我不知道為什么如果共享實例它會變得更快,我猜它會緩存陰影的渲染並且可以將它重用於視圖中的其他實例。 我想知道這是否更快

暫無
暫無

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

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