UIView with rounded corners and drop shadow?

前端 未结 30 2607
一整个雨季
一整个雨季 2020-11-22 08:00

I’ve been working on an application for a couple of years and received a simple design request: Round the corners on a UIView and add a drop shadow.To do as given below.

相关标签:
30条回答
  • 2020-11-22 08:19
    import UIKit
    
    extension UIView {
    
        func addShadow(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
    
            let shadowLayer = CAShapeLayer()
            let size = CGSize(width: cornerRadius, height: cornerRadius)
            let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
            shadowLayer.path = cgPath //2
            shadowLayer.fillColor = fillColor.cgColor //3
            shadowLayer.shadowColor = shadowColor.cgColor //4
            shadowLayer.shadowPath = cgPath
            shadowLayer.shadowOffset = offSet //5
            shadowLayer.shadowOpacity = opacity
            shadowLayer.shadowRadius = shadowRadius
            self.layer.addSublayer(shadowLayer)
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:20

    Swift 3 & IBInspectable solution:
    Inspired by Ade's solution

    First, create an UIView extension:

    //
    //  UIView-Extension.swift
    //  
    
    import Foundation
    import UIKit
    
    @IBDesignable
    extension UIView {
         // Shadow
         @IBInspectable var shadow: Bool {
              get {
                   return layer.shadowOpacity > 0.0
              }
              set {
                   if newValue == true {
                        self.addShadow()
                   }
              }
         }
    
         fileprivate func addShadow(shadowColor: CGColor = UIColor.black.cgColor, shadowOffset: CGSize = CGSize(width: 3.0, height: 3.0), shadowOpacity: Float = 0.35, shadowRadius: CGFloat = 5.0) {
              let layer = self.layer
              layer.masksToBounds = false
    
              layer.shadowColor = shadowColor
              layer.shadowOffset = shadowOffset
              layer.shadowRadius = shadowRadius
              layer.shadowOpacity = shadowOpacity
              layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath
    
              let backgroundColor = self.backgroundColor?.cgColor
              self.backgroundColor = nil
              layer.backgroundColor =  backgroundColor
         }
    
    
         // Corner radius
         @IBInspectable var circle: Bool {
              get {
                   return layer.cornerRadius == self.bounds.width*0.5
              }
              set {
                   if newValue == true {
                        self.cornerRadius = self.bounds.width*0.5
                   }
              }
         }
    
         @IBInspectable var cornerRadius: CGFloat {
              get {
                   return self.layer.cornerRadius
              }
    
              set {
                   self.layer.cornerRadius = newValue
              }
         }
    
    
         // Borders
         // Border width
         @IBInspectable
         public var borderWidth: CGFloat {
              set {
                   layer.borderWidth = newValue
              }
    
              get {
                   return layer.borderWidth
              }
         }
    
         // Border color
         @IBInspectable
         public var borderColor: UIColor? {
              set {
                   layer.borderColor = newValue?.cgColor
              }
    
              get {
                   if let borderColor = layer.borderColor {
                        return UIColor(cgColor: borderColor)
                   }
                   return nil
              }
         }
    }
    

    Then, simply select your UIView in interface builder setting shadow ON and corner radius, like below:

    The result!

    0 讨论(0)
  • 2020-11-22 08:21

    Swift 4 : Create Subclass of UIView

    class ShadowView: UIView {
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            // corner radius
            self.layer.cornerRadius = 10
    
            // border
            self.layer.borderWidth = 1.0
            self.layer.borderColor = UIColor.black.cgColor
    
            // shadow
            self.layer.shadowColor = UIColor.black.cgColor
            self.layer.shadowOffset = CGSize(width: 3, height: 3)
            self.layer.shadowOpacity = 0.7
            self.layer.shadowRadius = 4.0
        }
    
    }
    

    Using..

    0 讨论(0)
  • 2020-11-22 08:22

    I've created a helper on UIView

    @interface UIView (Helper)
    
    - (void)roundCornerswithRadius:(float)cornerRadius
                   andShadowOffset:(float)shadowOffset;
    @end
    

    you can call it like this

    [self.view roundCornerswithRadius:5 andShadowOffset:5];
    

    Here's the implementation

    - (void)roundCornerswithRadius:(float)cornerRadius
                   andShadowOffset:(float)shadowOffset
    {
        const float CORNER_RADIUS = cornerRadius;
        const float SHADOW_OFFSET = shadowOffset;
        const float SHADOW_OPACITY = 0.5;
        const float SHADOW_RADIUS = 3.0;
    
        UIView *superView = self.superview;
    
        CGRect oldBackgroundFrame = self.frame;
        [self removeFromSuperview];
    
        CGRect frameForShadowView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
        UIView *shadowView = [[UIView alloc] initWithFrame:frameForShadowView];
        [shadowView.layer setShadowOpacity:SHADOW_OPACITY];
        [shadowView.layer setShadowRadius:SHADOW_RADIUS];
        [shadowView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];
    
        [self.layer setCornerRadius:CORNER_RADIUS];
        [self.layer setMasksToBounds:YES];
    
        [shadowView addSubview:self];
        [superView addSubview:shadowView];
    
    }
    
    0 讨论(0)
  • 2020-11-22 08:23

    You need to use use shadowView and roundView

    shadowView

    • Must has background color
    • Should lay behind roundView
    • The trick is to layout shadowView a bit inside, and its shadow needs to glow out. Adjust the insets so that shadowView is completely invisible behind roundView

    roundView

    • Must clips subviews

    The code

    addSubviews(shadowView, roundView)
    roundView.addSubviews(titleLabel, subtitleLabel, imageView)
    
    // need inset
    shadowView.pinEdges(view: self, inset: UIEdgeInsets(constraintInsets: 2))
    roundView.pinEdges(view: self)
    
    do {
      shadowView.backgroundColor = .white // need background
      let layer = shadowView.layer
      layer.shadowColor = UIColor.black.cgColor
      layer.shadowRadius = 3
      layer.shadowOffset = CGSize(width: 3, height: 3)
      layer.shadowOpacity = 0.7
      layer.shouldRasterize = true
    }
    
    do {
      roundView.backgroundColor = .white
      let layer = roundView.layer
      layer.masksToBounds = true
      layer.cornerRadius = 5
    }
    

    Or you can just do below without specifying clipToBounds/maskToBounds

    layer.shadowColor = UIColor.gray.cgColor
    layer.shadowOffset = CGSize(width: 3, height: 3)
    layer.shadowOpacity = 0.8
    
    0 讨论(0)
  • 2020-11-22 08:24

    Old thread still current...

    I've edited Daniel Gindi's method to make it possible to use it with buttons etc. as well. If anyone needs rounded corners or wants to combine round corners and a border it has to be set on the view's layer which is passed to this method. I've also set the rasterization to speed it up a little.

    + (UIView*)putView:(UIView*)view insideShadowWithColor:(CGColorRef)color 
                                     andRadius:(CGFloat)shadowRadius 
                                     andOffset:(CGSize)shadowOffset 
                                     andOpacity:(CGFloat)shadowOpacity
    {
        // Must have same position like "view"
        UIView *shadow = [[UIView alloc] initWithFrame:view.frame]; 
    
        shadow.layer.contentsScale = [UIScreen mainScreen].scale;
        shadow.userInteractionEnabled = YES; // Modify this if needed
        shadow.layer.shadowColor = color;
        shadow.layer.shadowOffset = shadowOffset;
        shadow.layer.shadowRadius = shadowRadius;
        shadow.layer.masksToBounds = NO;
        shadow.clipsToBounds = NO;
        shadow.layer.shadowOpacity = shadowOpacity;
        shadow.layer.rasterizationScale = [UIScreen mainScreen].scale;
        shadow.layer.shouldRasterize = YES;
    
        [view.superview insertSubview:shadow belowSubview:view];
        [shadow addSubview:view];
    
        // Move view to the top left corner inside the shadowview 
        // ---> Buttons etc are working again :)
        view.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
    
        return shadow;
    }
    
    0 讨论(0)
提交回复
热议问题