Parent TabBar 剪辑 Children ViewControllers 的底部
Parent TabBar Clips Bottom of Children ViewControllers
我有一个 tabBarController
,通过 caShapeLayer
弯曲 tabBar
。
我的问题是矩形框 tabBar
夹住了 children viewControllers
的底部。
我的 goal/hope 是通过 弯曲的 框架进入并夹住底部。请参阅图片以供参考。
任何指导将不胜感激。
TabBarController 中弯曲 TabBar 的代码
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
self.tabBar.backgroundColor = .clear
self.tabBar.barStyle = .default
self.tabBar.isTranslucent = false
self.tabBar.clipsToBounds = false
hideTabBarBorder()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addTabBarShape()
}
func addTabBarShape() {
let shapeLayer = CAShapeLayer()
let offset:CGFloat = tabBar.bounds.width/3.5
let bounds: CGRect = tabBar.bounds
let rectBounds: CGRect = CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height / 2), width: bounds.size.width, height: bounds.size.height / 2)
let rectPath: UIBezierPath = UIBezierPath(rect: rectBounds)
let ovalBounds: CGRect = CGRect(x: bounds.origin.x - (offset / 2), y: bounds.origin.y, width: bounds.size.width + offset, height: bounds.size.height)
let ovalPath: UIBezierPath = UIBezierPath(ovalIn: ovalBounds)
rectPath.append(ovalPath)
shapeLayer.path = rectPath.cgPath
shapeLayer.fillColor = .blue
shapeLayer.shadowPath = rectPath.cgPath
shapeLayer.shadowColor = UIColor.black.cgColor
shapeLayer.shadowOpacity = 0.1
shapeLayer.shadowRadius = 20
shapeLayer.shadowOffset = CGSize(width: 0, height: -8)
shapeLayer.shouldRasterize = true
shapeLayer.rasterizationScale = UIScreen.main.scale
if let oldShapeLayer = self.tabBarShapeLayer {
self.tabBar.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.tabBar.layer.insertSublayer(shapeLayer, at: 0)
}
self.tabBarShapeLayer = shapeLayer
}
func hideTabBarBorder() {
self.tabBar.backgroundImage = UIImage.from(color: Constants.style.darkBlue)
self.tabBar.shadowImage = UIImage()
}
extension UIImage {
static func from(color: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
这是因为子 ViewController 没有更新其约束,它指的是同一个 tabcontroller 约束。您只需要查看控制器的底部约束。我在这里使用 snapkit 在视图出现之前修复约束。您可以将控制器底部边距设置为与 superView 相等,并在控制器内处理标签栏偏移量。
这基本上会忽略底部标签栏的存在。
import UIKit
import SnapKit
class SomeViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateConstraints()
}
func updateConstraints() {
view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}
我的解决方法是在比 tabBar 框架 y-point 更高的位置绘制曲线...
您必须将 backgroundImage
设置为不可见的内容,以使视图看起来像是被标签栏剪裁了。
我不确定为什么在您的示例中将其明确设置为 UIImage.from(color: Constants.style.darkBlue)
。
以下 + 复制所有其他代码对我来说工作得很好:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addTabBarShape()
tabBar.backgroundImage = UIImage()
tabBar.shadowImage = UIImage()
}
还要确保连接视图的底部锚点(例如 UITableView
) 而不是 到 view.safeAreaLayoutGuide.bottomAnchor
(就像您通常那样)而是 view.bottomAnchor
让它看起来被 tabBar 截断了。
(更改了该实现中的一些颜色,但在这里您可以看到它如何剪辑 UITableView
)
我有一个 tabBarController
,通过 caShapeLayer
弯曲 tabBar
。
我的问题是矩形框 tabBar
夹住了 children viewControllers
的底部。
我的 goal/hope 是通过 弯曲的 框架进入并夹住底部。请参阅图片以供参考。
任何指导将不胜感激。
TabBarController 中弯曲 TabBar 的代码
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
self.tabBar.backgroundColor = .clear
self.tabBar.barStyle = .default
self.tabBar.isTranslucent = false
self.tabBar.clipsToBounds = false
hideTabBarBorder()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addTabBarShape()
}
func addTabBarShape() {
let shapeLayer = CAShapeLayer()
let offset:CGFloat = tabBar.bounds.width/3.5
let bounds: CGRect = tabBar.bounds
let rectBounds: CGRect = CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height / 2), width: bounds.size.width, height: bounds.size.height / 2)
let rectPath: UIBezierPath = UIBezierPath(rect: rectBounds)
let ovalBounds: CGRect = CGRect(x: bounds.origin.x - (offset / 2), y: bounds.origin.y, width: bounds.size.width + offset, height: bounds.size.height)
let ovalPath: UIBezierPath = UIBezierPath(ovalIn: ovalBounds)
rectPath.append(ovalPath)
shapeLayer.path = rectPath.cgPath
shapeLayer.fillColor = .blue
shapeLayer.shadowPath = rectPath.cgPath
shapeLayer.shadowColor = UIColor.black.cgColor
shapeLayer.shadowOpacity = 0.1
shapeLayer.shadowRadius = 20
shapeLayer.shadowOffset = CGSize(width: 0, height: -8)
shapeLayer.shouldRasterize = true
shapeLayer.rasterizationScale = UIScreen.main.scale
if let oldShapeLayer = self.tabBarShapeLayer {
self.tabBar.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.tabBar.layer.insertSublayer(shapeLayer, at: 0)
}
self.tabBarShapeLayer = shapeLayer
}
func hideTabBarBorder() {
self.tabBar.backgroundImage = UIImage.from(color: Constants.style.darkBlue)
self.tabBar.shadowImage = UIImage()
}
extension UIImage {
static func from(color: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
这是因为子 ViewController 没有更新其约束,它指的是同一个 tabcontroller 约束。您只需要查看控制器的底部约束。我在这里使用 snapkit 在视图出现之前修复约束。您可以将控制器底部边距设置为与 superView 相等,并在控制器内处理标签栏偏移量。
这基本上会忽略底部标签栏的存在。
import UIKit
import SnapKit
class SomeViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateConstraints()
}
func updateConstraints() {
view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}
我的解决方法是在比 tabBar 框架 y-point 更高的位置绘制曲线...
您必须将 backgroundImage
设置为不可见的内容,以使视图看起来像是被标签栏剪裁了。
我不确定为什么在您的示例中将其明确设置为 UIImage.from(color: Constants.style.darkBlue)
。
以下 + 复制所有其他代码对我来说工作得很好:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addTabBarShape()
tabBar.backgroundImage = UIImage()
tabBar.shadowImage = UIImage()
}
还要确保连接视图的底部锚点(例如 UITableView
) 而不是 到 view.safeAreaLayoutGuide.bottomAnchor
(就像您通常那样)而是 view.bottomAnchor
让它看起来被 tabBar 截断了。
(更改了该实现中的一些颜色,但在这里您可以看到它如何剪辑 UITableView
)