【发布时间】:2021-03-15 07:16:20
【问题描述】:
使用iOS14.2、Swift5.3.1、Xcode 12.2,
按照this link,我实现了一个具有新形状的自定义TabBar。
形状由 CAShapeLayer 及其对应的 BezierPath 给出(参见下面的代码示例)。
但是,我想模糊这个自定义 TabBar,保持 BezierPath 形状作为它的遮罩,同时保持模糊透明。
请参阅最底部的附加视频,以说明我的意思。
这是自定义 TabBar 形状的代码(这部分效果很好)
import UIKit
@IBDesignable
class CustomTabBar: UITabBar {
private var shapeLayer: CALayer?
var scanTabShown = true
override func draw(_ rect: CGRect) {
self.addShape()
}
private func addShape() {
let shapeLayer = CAShapeLayer()
shapeLayer.path = self.createPath()
shapeLayer.strokeColor = UIColor.lightGray.cgColor
shapeLayer.fillColor = #colorLiteral(red: 0.9782002568, green: 0.9782230258, blue: 0.9782107472, alpha: 0.75)
shapeLayer.lineWidth = 0.5
shapeLayer.shadowOffset = CGSize(width:0, height:0)
shapeLayer.shadowRadius = 10
shapeLayer.shadowColor = UIColor.gray.cgColor
shapeLayer.shadowOpacity = 0.3
if let oldShapeLayer = self.shapeLayer {
self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.layer.insertSublayer(shapeLayer, at: 0)
}
self.shapeLayer = shapeLayer
}
func createPath() -> CGPath {
let height: CGFloat = 72.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
if scanTabShown {
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: (centerWidth - 31 ), y: 0))
path.addCurve(to: CGPoint(x: centerWidth, y: height - 40),
controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 29, y: height - 40))
path.addCurve(to: CGPoint(x: (centerWidth + 31 ), y: 0),
controlPoint1: CGPoint(x: centerWidth + 29, y: height - 40), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.close()
} else {
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.close()
}
return path.cgPath
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
for member in subviews.reversed() {
let subPoint = member.convert(point, from: self)
guard let result = member.hitTest(subPoint, with: event) else { continue }
return result
}
return nil
}
}
extension UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 83
return sizeThatFits
}
}
为了实现蒙版的BlurView,我关注了this link。
这是我的代码,据说应该为这个自定义形状的 TabBar 添加模糊效果。
但是代码仍然不起作用。怎么了?
在addShape() 方法中,我添加了以下代码以获得所需的效果。但同样,它不起作用。为什么???
let maskLayer = CAShapeLayer()
maskLayer.path = shapeLayer.path
maskLayer.fillRule = .evenOdd
let maskView = UIView(frame: self.frame)
maskView.backgroundColor = UIColor.black
maskView.layer.mask = maskLayer
let blurEffect = UIBlurEffect(style: .regular)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = self.frame
blurEffectView.alpha = 1.0
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
blurEffectView.mask = maskView
self.layer.addSublayer(blurEffectView.layer)
这里有一个插图:
请注意,顶部的导航栏显示了所需的半透明和模糊行为。
底部带有 BezierPath 的 TabBar 是完全白色的。但我也希望它是半透明和模糊的......我怎样才能做到这一点?
我已经尝试使用shapeLayer.fillColor 的 alpha 值。半透明正在工作。但不是模糊!!!
另一个尝试是将自定义形状的 tabBar 模糊为 tabBarController 中的 subView。但同样,没有模糊!
这里是试用的代码:
class SessionTabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if let tabBar = self.tabBar as? CustomTabBar {
let maskLayer = CAShapeLayer()
maskLayer.path = tabBar.createPath()
maskLayer.fillRule = .evenOdd
let maskView = UIView(frame: tabBar.frame)
maskView.backgroundColor = UIColor.black
maskView.layer.mask = maskLayer
let blurEffect = UIBlurEffect(style: .regular)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.backgroundColor = .green
blurEffectView.tintColor = .yellow
blurEffectView.frame = tabBar.frame
blurEffectView.alpha = 1.0
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
blurEffectView.mask = maskView
tabBar.addSubview(blurEffectView)
self.view.bringSubviewToFront(tabBar)
}
}
}
【问题讨论】:
-
您能否提供一张图片说明您正在努力实现的目标以及您已经设法实现的目标?
-
@Sti:我在原始问题中添加了一个短视频。请不要顶部导航栏的半透明和模糊。但是,底部的 TabBar 不会显示相同的效果。如何实现自定义绘制的 TabBar 的模糊?
-
Hm.. 也许尝试将 UIVisualEffectView 作为子视图添加到您的自定义选项卡视图,并将遮罩/形状应用到该视图?
-
不幸的是,您将其作为自定义选项卡视图的子视图添加的建议也不起作用!请参阅解释我尝试过的原始帖子中的附加代码。还有其他方法可以模糊自定义形状的 tabBar 吗?
标签: swift uikit uitabbarcontroller draw cashapelayer