【问题标题】:how to make cropped UIView to show the bottom of that UIView?如何使裁剪的 UIView 显示该 UIView 的底部?
【发布时间】:2019-02-01 02:45:39
【问题描述】:

我需要做这样的事情

如您所见,左右两侧有两个半圆形视图,会显示底部的UIView(UIView,背景为深蓝色)。如何实现呢?

我把问题简化成如下图:

我应该对那个white view 做些什么来制作裁剪效果并实际显示背景视图(蓝色视图)?

编辑:不,我不能为那个白色视图赋予蓝色。正如您在第一张图片中看到的,背景颜色实际上是渐变色,这就是为什么我需要“裁剪”这个 UIView 以显示底部 UIView 的背景颜色

【问题讨论】:

  • 嗯,最明显的答案是 - 给它与视图背景视图相同的背景颜色?
  • 不,在这种情况下不能这样。因为背景颜色是渐变色
  • 几个月前我也做过同样的事情。如果您还需要它,我会与您分享。

标签: ios swift uiview


【解决方案1】:

这是您想要实现的视图。目标是您需要使用角和弧线绘制此视图。如果你需要任何帮助或解释我是如何做到的,你可以问。

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .blue
    view.addSubview(croppedView)

    croppedView.cutViewCornersWith(cornerRadius: 20, arcRadius: 14)
}

lazy var croppedView: CroppedView = {
    let cv = CroppedView(frame: CGRect(x: 0,
                                       y: 0,
                                       width: self.view.frame.width - 120,
                                       height: 400))
    cv.center = view.center
    cv.backgroundColor = .lightGray
    return cv
}()

}

import UIKit

class CroppedView: UIView {

func cutViewCornersWith(cornerRadius: CGFloat, arcRadius: CGFloat) {
    let path = UIBezierPath()

    let width = self.frame.width
    let height = self.frame.height
    let arcCenter = height - height/3

    path.move(to: CGPoint(x: 0, y: cornerRadius))

    path.addArc(withCenter: CGPoint(x: cornerRadius, y: cornerRadius),
                radius: cornerRadius,
                startAngle: CGFloat(180.0).toRadians(),
                endAngle: CGFloat(270.0).toRadians(),
                clockwise: true)

    path.addLine(to: CGPoint(x: width - cornerRadius, y: 0.0))

    path.addArc(withCenter: CGPoint(x: width - cornerRadius, y: cornerRadius),
                radius: cornerRadius,
                startAngle: CGFloat(90.0).toRadians(),
                endAngle: CGFloat(0.0).toRadians(),
                clockwise: true)

    path.addLine(to: CGPoint(x: width, y: arcCenter - arcRadius))

    path.addArc(withCenter: CGPoint(x: width, y: arcCenter),
                radius: arcRadius,
                startAngle: CGFloat(270.0).toRadians(),
                endAngle: CGFloat(90.0).toRadians(),
                clockwise: false)

    path.addLine(to: CGPoint(x: width, y: height - cornerRadius))

    path.addArc(withCenter: CGPoint(x: width - cornerRadius, y: height - cornerRadius),
                radius: cornerRadius,
                startAngle: CGFloat(0.0).toRadians(),
                endAngle: CGFloat(90.0).toRadians(),
                clockwise: true)

    path.addLine(to: CGPoint(x: cornerRadius, y: height))

    path.addArc(withCenter: CGPoint(x: cornerRadius, y: height - cornerRadius),
                radius: cornerRadius,
                startAngle: CGFloat(90.0).toRadians(),
                endAngle: CGFloat(180.0).toRadians(),
                clockwise: true)

    path.addLine(to: CGPoint(x: 0, y: arcCenter + arcRadius))

    path.addArc(withCenter: CGPoint(x: 0, y: arcCenter),
                radius: arcRadius,
                startAngle: CGFloat(90.0).toRadians(),
                endAngle: CGFloat(270.0).toRadians(),
                clockwise: false)

    path.addLine(to: CGPoint(x: 0, y: arcCenter - arcRadius))
    path.addLine(to: CGPoint(x: 0, y: 0))

    path.close()

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path.cgPath
    self.layer.mask = shapeLayer
}

}

extension CGFloat {
    func toRadians() -> CGFloat {
        return self * .pi / 180.0
    }
}

【讨论】:

    【解决方案2】:

    有一种方法可以在代码中做到这一点。您需要设置一个“掩码”。我不确定你是否可以使用 InterfaceBuilder 来做到这一点(我很清楚它)。这是我使用的代码的要点(从我的代码中截取,但未经测试)。在这里,我制作了一个透明条,其宽度为视图宽度,holeHeight 高度 - 我自定义绘制了选取器的中间。

    class HoledView: UIView {
        override func draw(_ rect: CGRect) {
            backgroundColor?.setFill()
            UIRectFill(rect)
            let layer = CAShapeLayer()
            let path = CGMutablePath()
            let rect = CGRect(x: 0, y: (self.frame.height - holeHeight) / 2, width: self.frame.width, height: holeHeight)
            path.addRect(rect)
            path.addRect(self.bounds)
            layer.path = path
            layer.fillRule = kCAFillRuleEvenOdd
            self.layer.mask = layer
        }
    }
    

    基本思想是遮罩定义了视图将进入的区域。在我的示例中,遮罩的中间有一个洞,因此视图不会进入该区域,并且它保持完全透明。

    虽然我是使用图层来做到这一点的,it may be doable using a mask view instead:

    视图的 Alpha 通道决定了视图的内容和背景的显示程度。完全或部分不透明的像素允许底层内容显示出来,但完全透明的像素会阻挡该内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      相关资源
      最近更新 更多