iOS开发:如何裁剪vendorBlock以隐藏其在SearchView下方的部分?
问题
我有一个名为SearchView的视图,还有一个带“lalal”标签的vendorBlock视图。目前遇到的问题是:给searchView.backgroundColor设置了透明度后,切换明暗模式时出现UI bug,vendorBlock在SearchView下方的部分透过半透明区域显示出来了,想知道怎么裁剪vendorBlock,让这部分不再可见。
相关代码如下:
视图初始化代码
private lazy var searchView: SearchView = { let view = SearchView() view.layer.cornerRadius = 20 view.delegate = self return view }() private var vendorBlock: UIView = { let view = UIView() view.layer.cornerRadius = 20 view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner] view.backgroundColor = AppColors.vendorView view.clipsToBounds = true return view }()
布局代码
private func linkLayout() { addSubview(vendorBlock) addSubview(searchView) searchView.snp.makeConstraints { make in make.top.leading.trailing.equalToSuperview() make.height.equalTo(248) } vendorBlock.snp.makeConstraints { make in make.top.equalTo(searchView.snp.bottom).inset(16) make.height.equalTo(46) make.leading.trailing.bottom.equalToSuperview() } addSubview(vendorLabel) vendorLabel.snp.makeConstraints { make in make.bottom.equalToSuperview().inset(8) make.leading.equalToSuperview().inset(16) } }
预期效果
- 效果示例1:
vendorBlock与SearchView的圆角衔接自然,被SearchView遮挡的部分完全不可见 - 效果示例2:浅色模式下,
vendorBlock仅露出下方带圆角的区域,顶部被SearchView完全覆盖 - 浅色模式预期效果:界面层级清晰,无重叠透显的问题
深色模式Bug表现
深色模式下,vendorBlock向上偏移的16pt部分透过半透明的SearchView显示出来,破坏了原本的界面层级,视觉效果异常。
解决方案
方法1:用容器视图裁剪(最稳妥)
给vendorBlock套一个容器视图,利用容器的clipsToBounds属性裁剪掉超出容器的部分,同时调整布局让容器刚好从SearchView底部开始。
步骤:
- 添加容器视图:
private lazy var vendorContainer: UIView = { let view = UIView() view.clipsToBounds = true // 开启裁剪 return view }()
- 修改布局代码:
private func linkLayout() { // 先加容器,再加searchView保证层级 addSubview(vendorContainer) vendorContainer.addSubview(vendorBlock) addSubview(searchView) // 容器从searchView底部开始,撑满剩余区域 vendorContainer.snp.makeConstraints { make in make.top.equalTo(searchView.snp.bottom) make.leading.trailing.bottom.equalToSuperview() } // vendorBlock顶部向上偏移16pt,但超出容器的部分会被裁剪 vendorBlock.snp.makeConstraints { make in make.top.equalTo(vendorContainer.snp.top).offset(-16) make.height.equalTo(46) make.leading.trailing.bottom.equalTo(vendorContainer) } // 原searchView和vendorLabel布局不变 searchView.snp.makeConstraints { make in make.top.leading.trailing.equalToSuperview() make.height.equalTo(248) } addSubview(vendorLabel) vendorLabel.snp.makeConstraints { make in make.bottom.equalToSuperview().inset(8) make.leading.equalToSuperview().inset(16) } }
方法2:给SearchView添加遮罩
因为SearchView是半透明的,默认它的透明区域不会遮挡下方视图,给它加一个形状遮罩,确保只有SearchView的实体区域能显示,透明区域直接挡住下方内容。
步骤:
- 修改
searchView初始化代码:
private lazy var searchView: SearchView = { let view = SearchView() view.layer.cornerRadius = 20 view.delegate = self // 创建和searchView一样的圆角遮罩 let maskLayer = CAShapeLayer() maskLayer.path = UIBezierPath(roundedRect: view.bounds, cornerRadius: 20).cgPath view.layer.mask = maskLayer return view }()
- 如果
SearchView尺寸会动态变化,要在layoutSubviews里更新遮罩路径:
override func layoutSubviews() { super.layoutSubviews() guard let maskLayer = searchView.layer.mask as? CAShapeLayer else { return } maskLayer.path = UIBezierPath(roundedRect: searchView.bounds, cornerRadius: 20).cgPath }
方法3:调整vendorBlock的圆角路径(精准适配)
直接修改vendorBlock的圆角路径,让它的顶部和SearchView的底部圆角完全贴合,同时避免向上延伸的部分。这种方式需要精确计算圆角位置,适合固定尺寸的场景:
private var vendorBlock: UIView = { let view = UIView() view.backgroundColor = AppColors.vendorView // 创建自定义路径:顶部左右两个角是直角,底部左右是圆角,同时顶部和searchView底部对齐 let path = UIBezierPath() // 起点在左上角 path.move(to: CGPoint(x: 0, y: 16)) // 画到右上角 path.addLine(to: CGPoint(x: view.bounds.width, y: 16)) // 画右下角圆角 path.addArc(withCenter: CGPoint(x: view.bounds.width - 20, y: view.bounds.height - 20), radius: 20, startAngle: 0, endAngle: .pi/2, clockwise: true) // 画到底部左侧 path.addLine(to: CGPoint(x: 20, y: view.bounds.height)) // 画左下角圆角 path.addArc(withCenter: CGPoint(x: 20, y: view.bounds.height - 20), radius: 20, startAngle: .pi/2, endAngle: .pi, clockwise: true) // 闭合路径 path.close() let maskLayer = CAShapeLayer() maskLayer.path = path.cgPath view.layer.mask = maskLayer return view }()
注意:如果vendorBlock尺寸变化,同样需要在layoutSubviews里更新路径。
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

