iOS:不使用CAGradientLayer为UIBezierPath填充半区异色
实现UIBezierPath滑块左右分色(无需CAGradientLayer)
好的,我来帮你搞定这个需求!不用CAGradientLayer也能轻松实现滑块thumb左侧绿色、右侧白色的效果,核心思路是把滑块轨迹路径按thumb当前位置分割成左右两部分,分别填充不同颜色。结合你提到的贝塞尔路径实现逻辑,我给你具体的代码方案:
核心步骤
- 确定分割点:根据滑块当前的数值计算出thumb的中心X坐标,作为轨迹的分割边界。
- 构造左右区域路径:基于原有的轨迹路径(圆角矩形),通过填充规则裁剪出左右两个独立区域。
- 分别填充颜色:对左侧区域填充绿色,右侧填充白色,最后再绘制轨迹边框和thumb本身。
具体代码实现
假设你在自定义滑块的draw(_ rect: CGRect)方法中实现绘制逻辑,代码可以这么写:
override func draw(_ rect: CGRect) { // 1. 计算轨迹区域和thumb当前位置(这里需要根据你的滑块逻辑替换成实际值) let trackHeight: CGFloat = 8 let trackRect = CGRect(x: bounds.minX + 10, y: bounds.midY - trackHeight/2, width: bounds.width - 20, height: trackHeight) let thumbCenterX: CGFloat = ... // 根据滑块当前value计算的thumb中心X坐标(比如minX + value对应的偏移量) // 2. 创建原轨迹的圆角路径(和你提供的代码逻辑一致) let trackPath = UIBezierPath(roundedRect: trackRect, cornerRadius: trackHeight/2) // 3. 绘制左侧绿色区域 UIColor.green.setFill() let leftClipPath = trackPath.copy() as! UIBezierPath // 添加覆盖右侧区域的矩形,用奇偶填充规则保留左侧 leftClipPath.append(UIBezierPath(rect: CGRect(x: thumbCenterX, y: trackRect.minY, width: trackRect.maxX - thumbCenterX, height: trackRect.height))) leftClipPath.usesEvenOddFillRule = true leftClipPath.fill() // 4. 绘制右侧白色区域 UIColor.white.setFill() let rightClipPath = trackPath.copy() as! UIBezierPath // 添加覆盖左侧区域的矩形,用奇偶填充规则保留右侧 rightClipPath.append(UIBezierPath(rect: CGRect(x: trackRect.minX, y: trackRect.minY, width: thumbCenterX - trackRect.minX, height: trackRect.height))) rightClipPath.usesEvenOddFillRule = true rightClipPath.fill() // 5. 绘制轨迹边框(如果需要的话,避免被填充颜色覆盖) UIColor.gray.setStroke() trackPath.lineWidth = 1 trackPath.stroke() // 6. 绘制thumb(沿用你原有的thumb路径代码即可) let thumbPath = UIBezierPath(ovalIn: CGRect(x: thumbCenterX - 12, y: bounds.midY - 12, width: 24, height: 24)) UIColor.white.setFill() thumbPath.fill() UIColor.gray.setStroke() thumbPath.stroke() }
关键细节提醒
- 实时更新重绘:当滑块值变化时,一定要调用
setNeedsDisplay()方法触发重绘,这样颜色分割线才会跟着thumb移动。 - 填充规则说明:这里用到
usesEvenOddFillRule,是为了让我们添加的矩形和原轨迹路径的重叠区域被“裁剪”掉,只保留我们需要的一侧区域。 - 适配原代码:如果你的原轨迹路径有特殊的形状(比如非标准圆角),只需要替换
trackPath的创建逻辑即可,分割填充的核心逻辑不变。
内容的提问来源于stack exchange,提问作者Michael Grigoryan
相关产品推荐
相关产品推荐

