【问题标题】:How to apply a bottom shadow to a given UIView, like for a keyboard key?如何将底部阴影应用于给定的 UIView,例如键盘键?
【发布时间】:2022-01-19 08:05:24
【问题描述】:

如何创建一个 UIView,其阴影类似于 iOS 键盘的按键?

我尝试添加一个 CALayer

view.layer.insertSublayer(shadowLayer, below: view.layer) // view is the keyboard key view

但我看不到新层这样做。你能帮帮我吗?

谢谢

【问题讨论】:

    标签: ios uiview uikit


    【解决方案1】:

    如果您使用 Debug View Hierarchy 检查键盘视图,您会看到“按键按钮”没有阴影 ...它们在底部有一条单点线。

    有多种方法可以做到这一点,但最简单的方法之一是添加一个白色CAShapeLayer,使视图层和形状层具有相同的大小和角半径,然后将形状层向上移动一个点。

    这是一个快速、简单的视图子类 - 标记为 @IBDesignable,因此您可以在 Storyboard/Interface Builder 中看到它:

    @IBDesignable
    class BottomShadowView: UIView {
        
        let topLayer = CAShapeLayer()
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        func commonInit() {
            
            // add the "white" layer
            layer.addSublayer(topLayer)
    
            // give both layers the same corner radius
            layer.cornerRadius = 8
            topLayer.cornerRadius = 8
    
            // set top layer to white
            topLayer.backgroundColor = UIColor.white.cgColor
            
            // if background color is not set, or is clear
            //  set it to dark gray
            if self.backgroundColor == nil || self.backgroundColor == .clear {
                self.backgroundColor = .darkGray
            }
            
        }
        override func prepareForInterfaceBuilder() {
            super.prepareForInterfaceBuilder()
            // if background color is not set, or is clear
            //  set it to dark gray
            if self.backgroundColor == nil || self.backgroundColor == .clear {
                self.backgroundColor = .darkGray
            }
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            // make top layer the same size as bounds
            //  offset up 1-point
            topLayer.frame = bounds.offsetBy(dx: 0, dy: -1.0)
        }
        
    }
    

    看起来像这样(在系统黄色背景上):

    为了清晰起见放大:

    我们还可以通过覆盖 draw() 而不是添加子层来获得稍微“重量更轻”的自定义视图:

    @IBDesignable
    class DrawBottomShadowView: UIView {
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        func commonInit() {
            // background color needs to be .clear
            self.backgroundColor = .clear
        }
        override func prepareForInterfaceBuilder() {
            super.prepareForInterfaceBuilder()
            self.backgroundColor = .clear
        }
        
        override func draw(_ rect: CGRect) {
            super.draw(rect)
            
            var r: CGRect!
            var pth: UIBezierPath!
            
            // if rounded rect for "bottom shadow line"
            //  goes all the way to the top, we'll get
            //  anti-alias artifacts at the top corners
            // so, we'll make it slightly smaller
            r = bounds.insetBy(dx: 0, dy: 2).offsetBy(dx: 0, dy: 2)
            
            pth = UIBezierPath(roundedRect: r, cornerRadius: 8)
            
            UIColor.darkGray.setFill()
            pth.fill()
            
            // "filled" rounded rect should be
            //  1-point shorter than height
            r = bounds
            r.size.height -= 1.0
            
            pth = UIBezierPath(roundedRect: r, cornerRadius: 8)
    
            UIColor.white.setFill()
            pth.fill()
            
        }
        
    }
    

    【讨论】:

      【解决方案2】:

      我认为您可以为此使用每个 UIView 附带的支持 CALayer。

          func keyLetterButtonView ( havingLetter letter : String) -> UIView
          {
              let v = UIView()
              let l = v.layer
              l.cornerRadius = 4.0
              l.shadowOpacity = 1.0
              l.shadowRadius = 0
              l.shadowColor = UIColor.systemGray.cgColor
              l.shadowOffset = CGSize ( width: 0, height: 1.0)
              v.backgroundColor = .systemGray6
              
              // Key letter
              let label = UILabel()
              label.font = UIFont.preferredFont(forTextStyle: .title3)
              label.textAlignment = .center
              label.text = letter
              v.addSubview ( label)
              
              var constraints = [NSLayoutConstraint]()
              for vv in [ v, label] {
                  vv.translatesAutoresizingMaskIntoConstraints = false
                  let sizeConstraints = [
                      vv.widthAnchor.constraint (
                          equalToConstant: 28.0
                      )
                    , vv.heightAnchor.constraint (
                          equalToConstant: 42.0
                      )
                  ]
                  constraints.append (
                      contentsOf: sizeConstraints
                  )
              }
              NSLayoutConstraint.activate ( constraints)
              
              return v
          }
      

      【讨论】:

        猜你喜欢
        • 2012-12-02
        • 2018-07-19
        • 2018-03-01
        • 1970-01-01
        • 2017-08-23
        • 2023-01-29
        • 2019-05-04
        • 2019-01-17
        • 2018-12-27
        相关资源
        最近更新 更多