Swift中CAShapeLayer.isHidden自动添加动画问题求助
没关系的,刚接触CAShapeLayer有疑问太正常啦😉,我来帮你理清楚怎么实现这个需求:
你的核心需求是UIScrollView向上滚动时线条跟着内容同步移动,向下滚动时线条固定不动,本质是根据滚动方向和偏移量动态控制CAShapeLayer的位置,我给你一套完整的实现思路和代码:
第一步:准备必要属性并初始化线条
首先我们需要记录几个关键值,比如线条的初始位置、它能到达的最高位置(用来控制向下滚动时的静止状态),代码如下:
import UIKit class YourViewController: UIViewController, UIScrollViewDelegate { // 你的滚动视图 @IBOutlet weak var mainScrollView: UIScrollView! // 要控制的线条图层 private let topLineLayer = CAShapeLayer() // 线条初始的Y坐标 private var initialLineY: CGFloat = 0.0 // 线条能到达的最高Y位置(限制向下滚动时不回落) private var minLineY: CGFloat = 0.0 override func viewDidLoad() { super.viewDidLoad() mainScrollView.delegate = self setupTopLine() } // 初始化CAShapeLayer线条 private func setupTopLine() { // 设置线条样式 topLineLayer.strokeColor = UIColor.systemBlue.cgColor topLineLayer.lineWidth = 2.0 // 绘制初始线条(比如在屏幕顶部下方100pt处) let linePath = UIBezierPath() let startPoint = CGPoint(x: 0, y: 100) let endPoint = CGPoint(x: view.bounds.width, y: 100) linePath.move(to: startPoint) linePath.addLine(to: endPoint) topLineLayer.path = linePath.cgPath // 记录初始位置 initialLineY = startPoint.y minLineY = initialLineY // 将图层添加到父视图 view.layer.addSublayer(topLineLayer) } }
第二步:在滚动代理里处理位置逻辑
核心逻辑分三种情况处理,代码和说明如下:
extension YourViewController { func scrollViewDidScroll(_ scrollView: UIScrollView) { let currentOffsetY = scrollView.contentOffset.y // 1. 处理下拉超出顶部的弹性效果 if currentOffsetY < 0 { topLineLayer.isHidden = false // 下拉时让线条回到初始位置 let resetPath = UIBezierPath() resetPath.move(to: CGPoint(x: 0, y: initialLineY)) resetPath.addLine(to: CGPoint(x: view.bounds.width, y: initialLineY)) topLineLayer.path = resetPath.cgPath minLineY = initialLineY return } // 计算线条应该到达的目标Y位置 let targetLineY = initialLineY - currentOffsetY if targetLineY < minLineY { // 2. 向上滚动:线条同步移动,更新最高位置 let updatedPath = UIBezierPath() updatedPath.move(to: CGPoint(x: 0, y: targetLineY)) updatedPath.addLine(to: CGPoint(x: view.bounds.width, y: targetLineY)) topLineLayer.path = updatedPath.cgPath minLineY = targetLineY } else { // 3. 向下滚动:线条保持在最高位置,不移动 // 这里不需要修改path,因为已经把minLineY固定在最高位置了 } } }
逻辑补充说明
- 初始化时固定线条的初始位置,同时把最高位置的初始值设为初始Y
- 向上滚动时,
contentOffset.y增大,用初始Y减去偏移量得到目标Y,让线条跟着内容往上走,同时更新最高位置 - 向下滚动时,目标Y会比当前最高位置大(也就是要往下移动),这时候不修改线条位置,它就会保持静止
- 下拉超出顶部时,让线条回到初始位置,符合弹性滚动的视觉逻辑
如果你更习惯通过修改CAShapeLayer的position而不是path来移动线条,逻辑是完全一致的,只需要把修改path的代码换成修改topLineLayer.position.y即可,两种方式都可行~
内容的提问来源于stack exchange,提问作者JT attack
相关产品推荐
相关产品推荐

