我正在尝试在 Cocoa Touch 中的 UIView
的底部边缘下绘制阴影。我知道我应该使用 CGContextSetShadow()
来绘制阴影,但是 Quartz 2D 编程指南有点模糊:
保存图形状态。调用函数 CGContextSetShadow,传递适当的值。执行所有要应用阴影的绘图。恢复图形状态
我在 UIView
子类中尝试了以下内容:
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
CGContextRestoreGState(currentContext);
[super drawRect: rect];
}
..但这对我不起作用,我对(a)下一步去哪里和(b)我是否需要对我的 UIView
做任何事情来完成这项工作?
一种更简单的方法是在初始化时设置视图的一些层属性:
self.layer.masksToBounds = NO;
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
您需要导入 QuartzCore。
#import <QuartzCore/QuartzCore.h>
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 8; // if you like rounded corners
self.layer.shadowOffset = CGSizeMake(-15, 20);
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 0.5;
这会减慢应用程序的速度。只要您的视图是明显的矩形,添加以下行可以提高性能:
self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
相同的解决方案,但只是提醒您:您可以直接在情节提要中定义阴影。
前任:
https://i.stack.imgur.com/BPrQV.png
UIView
或 CGLayer
定义一个类别,它是 CGColor
属性的 UIColor
包装器;)
在您当前的代码中,您保存当前上下文的 GState
,将其配置为绘制阴影 .. 并将其恢复到配置为绘制阴影之前的状态。然后,最后,您调用超类的 drawRect
: 实现。
任何应该受阴影设置影响的绘图都需要在之后发生
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
但之前
CGContextRestoreGState(currentContext);
因此,如果您希望超类的 drawRect:
被“包裹”在阴影中,那么如果您像这样重新排列您的代码呢?
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
[super drawRect: rect];
CGContextRestoreGState(currentContext);
}
你可以试试这个....你可以玩这些价值观。 shadowRadius
指示模糊量。 shadowOffset
指示阴影的去向。
斯威夫特 2.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.CGPath
斯威夫特 3.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.black.cgColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.cgPath
传播示例
https://i.stack.imgur.com/z4pwm.png
创建基本阴影
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSizeMake(0.5, 4.0); //Here your control your spread
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
Swift 2.0 中的基本阴影示例
https://i.stack.imgur.com/OjGBu.png
使用 Interface Builder 的简单而干净的解决方案
在您的项目中添加一个名为 UIView.swift 的文件(或将其粘贴到任何文件中):
import UIKit
@IBDesignable extension UIView {
/* The color of the shadow. Defaults to opaque black. Colors created
* from patterns are currently NOT supported. Animatable. */
@IBInspectable var shadowColor: UIColor? {
set {
layer.shadowColor = newValue!.CGColor
}
get {
if let color = layer.shadowColor {
return UIColor(CGColor:color)
}
else {
return nil
}
}
}
/* The opacity of the shadow. Defaults to 0. Specifying a value outside the
* [0,1] range will give undefined results. Animatable. */
@IBInspectable var shadowOpacity: Float {
set {
layer.shadowOpacity = newValue
}
get {
return layer.shadowOpacity
}
}
/* The shadow offset. Defaults to (0, -3). Animatable. */
@IBInspectable var shadowOffset: CGPoint {
set {
layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
}
get {
return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
}
}
/* The blur radius used to create the shadow. Defaults to 3. Animatable. */
@IBInspectable var shadowRadius: CGFloat {
set {
layer.shadowRadius = newValue
}
get {
return layer.shadowRadius
}
}
}
然后,这将在 Interface Builder 中为 Utilities Panel > Attributes Inspector 中的每个视图提供:
https://i.stack.imgur.com/N5Uox.png
您现在可以轻松设置阴影。
注意: - 阴影不会出现在 IB 中,仅在运行时出现。 - 正如 Mazen Kasser 所说
对于那些未能使其正常工作的人[...]确保未启用剪辑子视图(clipsToBounds)
Failed to set (shadowColor) user defined inspected property on (UICollectionViewCell): [<UICollectionViewCell> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key shadowColor.
UIKit
才能使其工作,XCode 创建的基本 Foundation
导入是不够的,但编译得很好。我应该复制整个源代码。感谢 Axel 提供了这个不错的解决方案。
我将其用作我的实用程序的一部分。有了这个,我们不仅可以设置阴影,还可以为任何 UIView
获得圆角。你也可以设置你喜欢的颜色阴影。通常黑色是首选,但有时,当背景不是白色时,您可能需要其他东西。这是我使用的 -
in utils.m
+ (void)roundedLayer:(CALayer *)viewLayer
radius:(float)r
shadow:(BOOL)s
{
[viewLayer setMasksToBounds:YES];
[viewLayer setCornerRadius:r];
[viewLayer setBorderColor:[RGB(180, 180, 180) CGColor]];
[viewLayer setBorderWidth:1.0f];
if(s)
{
[viewLayer setShadowColor:[RGB(0, 0, 0) CGColor]];
[viewLayer setShadowOffset:CGSizeMake(0, 0)];
[viewLayer setShadowOpacity:1];
[viewLayer setShadowRadius:2.0];
}
return;
}
要使用它,我们需要调用它 - [utils roundedLayer:yourview.layer radius:5.0f shadow:YES];
斯威夫特 3
extension UIView {
func installShadow() {
layer.cornerRadius = 2
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 1)
layer.shadowOpacity = 0.45
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shadowRadius = 1.0
}
}
installShadow()
没有从 viewDidLoad()
或 viewWillAppear()
调用
draw
视图方法调用它。阴影正确出现,但圆角没有。
UIStackView
,它只进行布局并且没有视图。您可能必须插入一个常规 UIView
作为所有内容的容器。
如果您想使用 StoryBoard 并且不想继续输入运行时属性,您可以轻松地创建视图扩展并使其在 Storyboard 中可用。
步骤 1. 创建扩展
extension UIView {
@IBInspectable var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue
}
}
@IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
@IBInspectable var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
}
}
@IBInspectable var maskToBound: Bool {
get {
return layer.masksToBounds
}
set {
layer.masksToBounds = newValue
}
}
}
https://i.stack.imgur.com/UlFpR.png
对于在此处尝试所有答案后未能使其正常工作的人(作为我自己!),只需确保在属性检查器中未启用剪辑子视图...
在 Swift 4 中使用 IBDesignable 和 IBInspectable 绘制阴影
如何使用它
https://i.stack.imgur.com/YOobC.gif
并排草图和 XCODE
https://i.stack.imgur.com/gtTgz.png
代码
@IBDesignable class ShadowView: UIView {
@IBInspectable var shadowColor: UIColor? {
get {
if let color = layer.shadowColor {
return UIColor(cgColor: color)
}
return nil
}
set {
if let color = newValue {
layer.shadowColor = color.cgColor
} else {
layer.shadowColor = nil
}
}
}
@IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
@IBInspectable var shadowOffset: CGPoint {
get {
return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
}
set {
layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
}
}
@IBInspectable var shadowBlur: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue / 2.0
}
}
@IBInspectable var shadowSpread: CGFloat = 0 {
didSet {
if shadowSpread == 0 {
layer.shadowPath = nil
} else {
let dx = -shadowSpread
let rect = bounds.insetBy(dx: dx, dy: dx)
layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}
}
输出
https://i.stack.imgur.com/haMSV.png
您可以使用我为阴影和角半径创建的实用函数,如下所示:
- (void)addShadowWithRadius:(CGFloat)shadowRadius withShadowOpacity:(CGFloat)shadowOpacity withShadowOffset:(CGSize)shadowOffset withShadowColor:(UIColor *)shadowColor withCornerRadius:(CGFloat)cornerRadius withBorderColor:(UIColor *)borderColor withBorderWidth:(CGFloat)borderWidth forView:(UIView *)view{
// drop shadow
[view.layer setShadowRadius:shadowRadius];
[view.layer setShadowOpacity:shadowOpacity];
[view.layer setShadowOffset:shadowOffset];
[view.layer setShadowColor:shadowColor.CGColor];
// border radius
[view.layer setCornerRadius:cornerRadius];
// border
[view.layer setBorderColor:borderColor.CGColor];
[view.layer setBorderWidth:borderWidth];
}
希望对你有帮助!!!
斯威夫特 3
self.paddingView.layer.masksToBounds = false
self.paddingView.layer.shadowOffset = CGSize(width: -15, height: 10)
self.paddingView.layer.shadowRadius = 5
self.paddingView.layer.shadowOpacity = 0.5
全部回答都很好,但我想再补充一点
如果您在有表格单元格时遇到问题,Deque 一个新单元格存在阴影不匹配,因此在这种情况下,您需要将阴影代码放在 layoutSubviews 方法中,以便它在所有条件下都能正常运行。
-(void)layoutSubviews{
[super layoutSubviews];
[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];
[VPShadow applyShadowView:self];
}
或在特定视图的 ViewControllers 中将阴影代码放在以下方法中,以便它运行良好
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self.viewShadow layoutIfNeeded];
[VPShadow applyShadowView:self.viewShadow];
}
我已经为新开发者修改了我的影子实现,以获得更通用的形式,例如:
/*!
@brief Add shadow to a view.
@param layer CALayer of the view.
*/
+(void)applyShadowOnView:(CALayer *)layer OffsetX:(CGFloat)x OffsetY:(CGFloat)y blur:(CGFloat)radius opacity:(CGFloat)alpha RoundingCorners:(CGFloat)cornerRadius{
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:cornerRadius];
layer.masksToBounds = NO;
layer.shadowColor = [UIColor blackColor].CGColor;
layer.shadowOffset = CGSizeMake(x,y);// shadow x and y
layer.shadowOpacity = alpha;
layer.shadowRadius = radius;// blur effect
layer.shadowPath = shadowPath.CGPath;
}
对于 Xamarian 同胞,答案的 Xamarin.iOS/C# 版本如下所示:
public override void DrawRect(CGRect area, UIViewPrintFormatter formatter)
{
CGContext currentContext = UIGraphics.GetCurrentContext();
currentContext.SaveState();
currentContext.SetShadow(new CGSize(-15, 20), 5);
base.DrawRect(area, formatter);
currentContext.RestoreState();
}
主要区别在于您获得了一个 CGContext
的实例,您可以在该实例上直接调用适当的方法。
您可以使用此 Extension
添加阴影
extension UIView {
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float)
{
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
let backgroundCGColor = backgroundColor?.cgColor
backgroundColor = nil
layer.backgroundColor = backgroundCGColor
}
}
你可以这样称呼它
your_Custom_View.addShadow(offset: CGSize(width: 0, height: 1), color: UIColor.black, radius: 2.0, opacity: 1.0)
不定期副业成功案例分享
#import <QuartzCore/QuartzCore.h>"
添加到 .h 文件。masksToBounds
设置为NO
将否定cornerRadius
,不是吗?self.layer.backgroundColor = [[UIColor whiteColor] CGColor];
但没有运气。哪个视图需要透明?