iOS纯代码实现自定义形状TabBarController问题求助
解决自定义TabBar形状不显示的问题
我来帮你搞定这个自定义TabBar没出效果的问题!咱们一步步梳理问题、修复代码:
1. 核心问题:没让TabBarController用上你的自定义TabBar
你已经写了CustomizedTabBar,但系统默认的UITabBarController还是在使用自带的UITabBar,之前重写tabBar属性没生效,大概率是写法不对。试试下面的方式替换系统TabBar:
修改你的CustomTabBarController代码:
import UIKit class CustomTabBarController: UITabBarController { // 初始化自定义TabBar实例 private let _customTabBar = CustomizedTabBar() override func viewDidLoad() { super.viewDidLoad() // 通过KVC替换系统默认的TabBar(因为tabBar属性是只读的) setValue(_customTabBar, forKey: "tabBar") setupCenterButton() } func setupCenterButton() { let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64)) var menuButtonFrame = menuButton.frame // 适配自定义TabBar的高度(64),让按钮刚好卡在凸起位置 menuButtonFrame.origin.y = view.bounds.height - menuButtonFrame.height - (64 - 34)/2 menuButtonFrame.origin.x = view.bounds.width/2 - menuButtonFrame.size.width/2 menuButton.frame = menuButtonFrame menuButton.clipsToBounds = true menuButton.layer.cornerRadius = menuButtonFrame.height/2 // 加个背景色方便测试 menuButton.backgroundColor = .systemBlue view.addSubview(menuButton) // 把按钮放到TabBar上层,避免被遮挡 view.bringSubviewToFront(menuButton) } }
2. 完善CustomizedTabBar的形状绘制逻辑
你的CustomizedTabBar里不仅路径是空的,还没给形状图层设置填充色,这也是形状不显示的关键。咱们完善成中间凸起的样式(适配你的中间按钮):
import UIKit class CustomizedTabBar: UITabBar { private var shapeLayer: CALayer? // 自定义TabBar高度,替换之前的全局扩展 override func sizeThatFits(_ size: CGSize) -> CGSize { return CGSize(width: size.width, height: 64) } private func addShape() { let shapeLayer = CAShapeLayer() shapeLayer.path = createPath() // 设置填充色,和TabBar背景色一致(或自定义) shapeLayer.fillColor = UIColor.systemBackground.cgColor // 可选:加边框 shapeLayer.strokeColor = UIColor.separator.cgColor shapeLayer.lineWidth = 1 // 替换旧图层或插入新图层 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 path = UIBezierPath() let tabBarHeight = self.bounds.height let centerBtnWidth: CGFloat = 64 let cornerRadius: CGFloat = 16 // 从左上角开始绘制路径 path.move(to: CGPoint(x: 0, y: 0)) // 左半部分直线到凸起左侧圆角 path.addLine(to: CGPoint(x: (self.bounds.width - centerBtnWidth)/2 - cornerRadius, y: 0)) // 凸起左上角圆角 path.addArc(withCenter: CGPoint(x: (self.bounds.width - centerBtnWidth)/2, y: cornerRadius), radius: cornerRadius, startAngle: .pi, endAngle: .pi/2, clockwise: true) // 凸起左侧竖线到底部圆角 path.addLine(to: CGPoint(x: (self.bounds.width - centerBtnWidth)/2, y: tabBarHeight - cornerRadius)) path.addArc(withCenter: CGPoint(x: (self.bounds.width - centerBtnWidth)/2 + cornerRadius, y: tabBarHeight), radius: cornerRadius, startAngle: .pi*3/2, endAngle: 0, clockwise: true) // 底部横线到凸起右侧圆角 path.addLine(to: CGPoint(x: (self.bounds.width + centerBtnWidth)/2 - cornerRadius, y: tabBarHeight)) path.addArc(withCenter: CGPoint(x: (self.bounds.width + centerBtnWidth)/2, y: tabBarHeight - cornerRadius), radius: cornerRadius, startAngle: 0, endAngle: .pi/2, clockwise: true) // 凸起右侧竖线到顶部圆角 path.addLine(to: CGPoint(x: (self.bounds.width + centerBtnWidth)/2, y: cornerRadius)) path.addArc(withCenter: CGPoint(x: (self.bounds.width + centerBtnWidth)/2 - cornerRadius, y: 0), radius: cornerRadius, startAngle: .pi/2, endAngle: 0, clockwise: true) // 右半部分直线到右上角,再闭合路径 path.addLine(to: CGPoint(x: self.bounds.width, y: 0)) path.addLine(to: CGPoint(x: self.bounds.width, y: tabBarHeight)) path.addLine(to: CGPoint(x: 0, y: tabBarHeight)) path.close() return path.cgPath } // 修复中间按钮的点击响应问题 override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { guard !clipsToBounds && !isHidden && alpha > 0 else { return nil } // 定义中间按钮的点击区域(超出TabBar的部分也要响应) let buttonHitArea = CGRect(x: (self.bounds.width - 64)/2, y: -20, width: 64, height: 64) if buttonHitArea.contains(point) { // 让父视图处理点击,确保中间按钮能响应 return self.superview?.hitTest(convert(point, to: self.superview), with: event) } return super.hitTest(point, with: event) } // 布局变化时重新绘制形状(比如旋转屏幕) override func layoutSubviews() { super.layoutSubviews() addShape() } }
3. 清理冗余代码
删掉之前写的UITabBar扩展,因为我们已经在CustomizedTabBar里重写了sizeThatFits方法。
现在运行代码,你的TabBar应该会显示中间凸起的自定义形状,中间按钮也能正常显示并响应点击了。如果需要调整形状样式,修改createPath里的路径逻辑即可。
内容的提问来源于stack exchange,提问作者asteezy24
相关产品推荐
相关产品推荐

