Swift自定义TabController切换标签时路径描边无法同步动画问题求解
问题原因
- 当前你实现的路径过渡动画只作用于图层遮罩(mask),描边是通过CoreGraphics的
stroke()方法直接绘制的静态内容,仅在drawCurve调用时渲染一次,不会跟随遮罩的path动画同步变化。 - 描边没有独立的动画载体,无法参与CoreAnimation的属性过渡。
解决步骤
- 新增全局持久化的
CAShapeLayer作为专门的描边层,不要每次调用drawCurve都重复创建 - 描边的样式、path都统一交给这个CAShapeLayer管理,删除
drawCurve里直接调用stroke()的逻辑 - 动画触发时,同时给遮罩层和描边层添加完全相同的path过渡动画
修改后参考代码
// 类内先声明持久化持有描边层 private let strokeLayer: CAShapeLayer = { let layer = CAShapeLayer() layer.lineWidth = 1 layer.fillColor = UIColor.clear.cgColor layer.strokeColor = Colors.borderTabbarGrayColor.cgColor return layer }() // 初始化时把描边层添加到当前视图的layer上 override init(frame: CGRect) { super.init(frame: frame) layer.addSublayer(strokeLayer) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func drawCurve() { let fillColor: UIColor = .white tabWidth = self.bounds.width / CGFloat(self.items!.count) let bezPath = drawPathBorder(for: index) bezPath.close() // 保留原有的填充逻辑 fillColor.setFill() bezPath.fill() let mask = CAShapeLayer() mask.fillRule = .evenOdd mask.path = bezPath.cgPath // 给描边层赋值最终状态的path strokeLayer.path = bezPath.cgPath if (self.animated) { let bezPathFrom = drawPathBorder(for: previousIndex) // 创建mask的path动画 let maskAnimation = CABasicAnimation(keyPath: "path") maskAnimation.fromValue = bezPathFrom.cgPath maskAnimation.toValue = bezPath.cgPath maskAnimation.duration = 3.3 maskAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) // 可选配置:避免动画结束后闪回 maskAnimation.fillMode = .forwards maskAnimation.isRemovedOnCompletion = false mask.add(maskAnimation, forKey: nil) // 同步给描边层添加相同的动画 let strokeAnimation = maskAnimation.copy() as! CABasicAnimation strokeLayer.add(strokeAnimation, forKey: "pathAnimation") } self.layer.mask = mask }
额外注意点
如果你的tabbar有布局变化需要适配,记得在layoutSubviews方法里同步更新strokeLayer的frame,避免描边位置偏移。
内容的提问来源于stack exchange,提问作者user883884
相关产品推荐
相关产品推荐

