Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何在视图下绘制阴影?_Iphone_Objective C_Ios_Cocoa Touch_Core Graphics - Fatal编程技术网

Iphone 如何在视图下绘制阴影?

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

我试图在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
    做些什么才能使它起作用?

    在当前代码中,保存当前上下文的
    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
                }
            }
        }
    }