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