【问题标题】:Draw shadow only from 3 sides of UIView仅从 UIView 的 3 个侧面绘制阴影
【发布时间】:2013-03-20 05:00:39
【问题描述】:

我已经成功地在我的UIView 周围画了一个阴影,如下所示:

block1.layer.masksToBounds = NO;
block1.layer.shadowOffset = CGSizeMake(0, 0);
block1.layer.shadowRadius = 1;
block1.layer.shadowOpacity = 0.7;

现在发生的事情是我有一个矩形UIView,我想在它的三个边上绘制阴影,留下它的 底部没有阴影.

我知道我必须通过创建一个新的UIBezierPath 来指定block1.layer.shadowPath,但我不知道该怎么做。

显然,设置 layer.shadowOffset 对我来说不起作用。

提前致谢!

【问题讨论】:

    标签: ios objective-c cocoa-touch uiview uikit


    【解决方案1】:

    我知道你说设置 layer.shadowOffset 对你不起作用,但你可以输入负值,所以设置它 layer.shadowOffset = CGSizeMake(0.0, -2.0) 会接近你正在寻找的效果,但我当然希望你希望它在三个方面是均匀的。

    所以我们在这里使用layer.shadowPath

    UIView *block1 = [[UIView alloc] initWithFrame:CGRectMake(32.0, 32.0, 128.0, 128.0)];
    [block1 setBackgroundColor:[UIColor orangeColor]];
    [self.view addSubview:block1];
    
    block1.layer.masksToBounds = NO;
    block1.layer.shadowOffset = CGSizeMake(0, 0);
    block1.layer.shadowRadius = 1;
    block1.layer.shadowOpacity = 0.7;
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    // Start at the Top Left Corner
    [path moveToPoint:CGPointMake(0.0, 0.0)];
    
    // Move to the Top Right Corner
    [path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), 0.0)];
    
    // Move to the Bottom Right Corner
    [path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame), CGRectGetHeight(block1.frame))];
    
    // This is the extra point in the middle :) Its the secret sauce.
    [path addLineToPoint:CGPointMake(CGRectGetWidth(block1.frame) / 2.0, CGRectGetHeight(block1.frame) / 2.0)];
    
    // Move to the Bottom Left Corner
    [path addLineToPoint:CGPointMake(0.0, CGRectGetHeight(block1.frame))];
    
    // Move to the Close the Path
    [path closePath];
    
    block1.layer.shadowPath = path.CGPath;
    

    为了让您了解发生了什么,这是您刚刚绘制的实际阴影路径:)

    可以将多余的中间点移动到其他行之前或之后,以选择省略哪一侧。

    【讨论】:

    • 这不适用于较大的shadowRadius,因为它可能会在使用shadowPath 创建的三角形区域之外流血。
    • 没错,您可以将路径调整为比这些演员表中正方形的其余部分短一点。
    【解决方案2】:

    更新 Ryan Poolos 对 Swift 3.0 的回答

    感谢 Ryan Poolos

    class sampleViewController: UIViewController {
        var block1: UIView! = nil
    
        override func viewDidLoad() {
    
            super.viewDidLoad()
            block1 = UIView(frame: CGRect(x: 32.0, y: 32.0, width: 128.0, height: 128.0))
            block1.backgroundColor = UIColor.orange
            self.view.addSubview(block1)
    
            block1.layer.masksToBounds = false
            block1.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
            block1.layer.shadowRadius = 1.0
            block1.layer.shadowOpacity = 0.7
    
            let path = UIBezierPath()
    
            // Start at the Top Left Corner
            path.move(to: CGPoint(x: 0.0, y: 0.0))
    
            // Move to the Top Right Corner
            path.addLine(to: CGPoint(x: block1.frame.size.width, y: 0.0))
    
            // Move to the Bottom Right Corner
            path.addLine(to: CGPoint(x: block1.frame.size.width, y: block1.frame.size.height))
    
            // This is the extra point in the middle :) Its the secret sauce.
            path.addLine(to: CGPoint(x: block1.frame.size.width/2.0, y: block1.frame.size.height/2.0))
    
            // Move to the Bottom Left Corner
            path.addLine(to: CGPoint(x: 0.0, y: block1.frame.size.height))
    
            path.close()
    
            block1.layer.shadowPath = path.cgPath
        }
    }
    

    结果:

    【讨论】:

      【解决方案3】:

      感谢Ashok R 的快速代码,对其他答案有所改进。

      由于我们在视图的背景中创建了一个三角形视图,所有边都有阴影,因此不需要在边上添加一个白色三角形阴影。

      如果视图的宽度相对大于高度,它会中断。

      解决方法是将不需要阴影的线的路径稍微移向视图的那一侧,而不是完全创建三角形视图路径

      我为此创建了一个扩展 -

      extension UIView {
          func addshadow(top: Bool,
                         left: Bool,
                         bottom: Bool,
                         right: Bool,
                         shadowRadius: CGFloat = 2.0) {
      
              self.layer.masksToBounds = false
              self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
              self.layer.shadowRadius = shadowRadius
              self.layer.shadowOpacity = 1.0
      
              let path = UIBezierPath()
              var x: CGFloat = 0
              var y: CGFloat = 0
              var viewWidth = self.frame.width
              var viewHeight = self.frame.height
      
              // here x, y, viewWidth, and viewHeight can be changed in
              // order to play around with the shadow paths.
              if (!top) {
                  y+=(shadowRadius+1)
              }
              if (!bottom) {
                  viewHeight-=(shadowRadius+1)
              }
              if (!left) {
                  x+=(shadowRadius+1)
              }
              if (!right) {
                  viewWidth-=(shadowRadius+1)
              }
              // selecting top most point
              path.move(to: CGPoint(x: x, y: y))
              // Move to the Bottom Left Corner, this will cover left edges
              /*
               |☐
               */
              path.addLine(to: CGPoint(x: x, y: viewHeight))
              // Move to the Bottom Right Corner, this will cover bottom edge
              /*
               ☐
               -
               */
              path.addLine(to: CGPoint(x: viewWidth, y: viewHeight))
              // Move to the Top Right Corner, this will cover right edge
              /*
               ☐|
               */
              path.addLine(to: CGPoint(x: viewWidth, y: y))
              // Move back to the initial point, this will cover the top edge
              /*
               _
               ☐
               */        
              path.close()
              self.layer.shadowPath = path.cgPath
          }
      

      并为您希望阴影出现的任何一侧设置布尔值 true

      myView.addshadow(top: false, left: true, bottom: true, right: true, shadowRadius: 2.0)

      //阴影半径在上面是可选的,默认设置为2.0

      myView.addshadow(top: true, left: true, bottom: true, right: true, shadowRadius: 2.0)

      myView.addshadow(top: false, left: false, bottom: true, right: true, shadowRadius: 2.0)

      【讨论】:

      • 如何给cornerRadius加上阴影。请更新您的答案
      【解决方案4】:

      试试这个

      extension CALayer {
      func applySketchShadow(color: UIColor, alpha: CGFloat, x: CGFloat, y: CGFloat, blur: CGFloat, spread: CGFloat)
      {
          shadowColor = color.cgColor
          shadowOpacity = alpha
          shadowOffset = CGSize(width: x, height: y)
          shadowRadius = blur / 2.0
          if spread == 0 {
              shadowPath = nil
          } else {
              let dx = -spread
              let rect = bounds.insetBy(dx: dx, dy: dx)
              shadowPath = UIBezierPath(rect: rect).cgPath
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-11-14
        • 2011-02-25
        • 1970-01-01
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多