Iphone 如何在视图下绘制阴影?
我试图在Cocoa Touch中的Iphone 如何在视图下绘制阴影?,iphone,objective-c,ios,cocoa-touch,core-graphics,Iphone,Objective C,Ios,Cocoa Touch,Core Graphics,我试图在Cocoa Touch中的UIView的底边下画一个阴影。我知道我应该使用CGContextSetShadow()来绘制阴影,但Quartz 2D编程指南有点模糊: 保存图形状态 调用函数CGContextSetShadow,传递适当的值 执行要应用阴影的所有图形 恢复图形状态 我在UIView子类中尝试了以下操作: - (void)drawRect:(CGRect)rect { CGContextRef currentContext = UIGraphicsGetCurrent
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
做些什么才能使它起作用?在当前代码中,保存当前上下文的GState
,将其配置为绘制阴影。。然后将其恢复到配置为绘制阴影之前的状态。最后,调用超类的drawRect
:
任何受阴影设置影响的图形都需要在
但之前
因此,如果您希望超类的drawRect:
被“包装”在阴影中,那么如果您像这样重新排列代码呢
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadow(currentContext, CGSizeMake(-15, 20), 5);
[super drawRect: rect];
CGContextRestoreGState(currentContext);
}
一种更简单的方法是在初始化时设置视图的某些图层属性:
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.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
我用它作为我的UTIL的一部分。这样,我们不仅可以设置阴影,还可以为任何
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]代码>相同的解决方案,但只是提醒您:您可以直接在情节提要中定义阴影
例:
对于那些未能实现此功能的人(作为我自己!),在尝试了这里的所有答案后,只需确保在属性检查器中未启用剪辑子视图…使用Interface Builder的简单而干净的解决方案
在项目中添加名为UIView.swift的文件(或将其粘贴到任何文件中):
然后,对于“实用程序”面板>“属性检查器”中的每个视图,Interface Builder中都会提供此选项:
现在可以轻松设置阴影
注:
-阴影不会出现在IB中,仅在运行时出现。
-正如马赞·卡斯尔所说
对于未能使其正常工作的用户[…]请确保未启用剪辑子视图(clipstobunds
)
你可以试试这个。。。。你可以利用这些价值观。
阴影半径
指示模糊量<代码>阴影偏移量
指示阴影的位置
Swift 2.0
Swift 3.0
传播的例子
创建基本阴影的步骤
Swift 2.0中的基本阴影示例
Swift 3
斯威夫特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
您可以使用为阴影和角半径创建的“我的实用程序”函数,如下所示:
- (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];
}
希望它能帮助你 答案都很好,但我想再补充一点 如果在使用表单元格时遇到问题,请确定一个新单元格阴影中存在不匹配,因此在这种情况下,需要将阴影代码放置在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;
}
如果您想使用情节提要,但不想继续在运行时属性中键入内容,则可以轻松创建视图的扩展,并使其在情节提要中可用 第一步。创建扩展名
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
}
}
}
第二步。现在,您可以在故事板中使用这些属性,对于Xamarin同伴,答案的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 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)
在Swift 4中使用IBDesignable和IBInspectable绘制阴影
如何使用它
并排绘制和XCODE
代码
输出
但请注意,这仅适用于iOS 3.2+版本,因此如果您的应用程序应适用于旧版本,则必须使用Christian的解决方案或视图后面的静态图像(如果这是一个选项)。此解决方案还需要添加#导入“
到.h文件。将masksToBounds
设置为NO
将否定cornerRadius
,否?好的,要解决这个问题,需要在图层上设置背景色,并且视图需要透明。@pixelfreak如何做到这一点?”?我尝试了self.layer.backgroundColor=[[UIColor-whiteColor]CGColor]代码>但是没有运气。哪种视图需要透明?可能值得注意的是,只有当您的视图明显为矩形时,此优化才有用。self.layer.shadowPath。。。而不是什么?或者只是添加到它上面,只是在其他线条之外添加额外的线条。@NathanGaskin-绘制阴影是一项昂贵的操作,例如,如果应用程序允许其他界面方向,并且您开始旋转设备,在不明确指定阴影路径的情况下,必须在动画期间多次渲染阴影,这可能会明显减慢速度,具体取决于形状animation@BenjaminDobell该特定线仅适用于矩形,但也可以创建非矩形路径。例如
- (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];
}
-(void)layoutSubviews{
[super layoutSubviews];
[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];
[VPShadow applyShadowView:self];
}
-(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;
}
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
}
}
}
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();
}
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)
@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
}
}
}
}