You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS使用CoreGraphics绘制UIView无法显示交替颜色问题求助

嘿,我来帮你搞定这个CoreGraphics绘制交替颜色没显示的问题~先从核心原理捋清楚,再结合你的ProgressMenuView代码找可能踩的坑。

先搞懂CoreGraphics的核心绘制逻辑

CoreGraphics(大伙常叫CG)是个状态机式的绘图框架,简单说就是:你得先给它设定好“当前状态”(比如填充色、线条粗细、要画的路径),然后喊它执行绘制指令,它就会用当前状态去渲染。而且状态是会累积的——除非你手动保存/恢复,不然后面的设置会直接覆盖前面的,这点很关键!

几个必走的绘制步骤:

  • 第一步:创建/添加**路径(CGPath)**到当前绘图上下文,比如画矩形就调用addRect(_:),画圆就用addArc(...)
  • 第二步:设置绘制状态,比如填充色UIColor.setFill()、描边色setStroke()
  • 第三步:执行绘制,调用fill()(填充)、stroke()(描边)或者fillStroke()(同时填充+描边)

要是这几步顺序错了(比如先画再设颜色),或者路径没加对,就会出现“啥也没画出来”的情况。

你的ProgressMenuView可能出问题的地方

看你的代码,应该是想画一段段不同颜色的进度条对吧?结合你没写完的cumul...(猜是累积值,用来算每段的宽度),我列几个最可能的坑:

1. 数值没转换成视图内的比例

你的values数组是[50,100,150,180],但这些原始数值得先转换成视图宽度范围内的比例才行!比如总数值是50+100+150+180=480,那每一段的宽度应该是(单个数值 / 总数值) * 视图宽度,不然数值超过视图宽度的话,后面的段直接画出视图外,自然看不到。

2. 没给每段单独设置颜色+绘制

CG是状态机,要是你循环的时候只改路径不改颜色,或者颜色设置在绘制之后,要么所有段都是最后一个颜色,要么干脆没颜色。正确的循环逻辑应该是这样:

override func draw(_ rect: CGRect) {
    // 先确保能拿到绘图上下文,拿不到直接返回
    guard let ctx = UIGraphicsGetCurrentContext() else { return }
    
    // 计算总数值,用来算每段的比例
    let totalValue = values.reduce(0, +)
    // 记录当前绘制的起始X坐标,一开始从0开始
    var currentX: CGFloat = 0
    
    // 遍历每个数值和对应的颜色
    for (index, value) in values.enumerated() {
        // 计算当前段的宽度
        let segmentWidth = (value / totalValue) * rect.width
        // 创建当前段的矩形路径
        let segmentRect = CGRect(x: currentX, y: 0, width: segmentWidth, height: rect.height)
        ctx.addRect(segmentRect)
        
        // 设置当前段的填充色
        colors[index].setFill()
        // 填充当前路径,注意fillPath()会清空当前路径,避免和下一段混在一起
        ctx.fillPath()
        
        // 更新起始X坐标,准备画下一段
        currentX += segmentWidth
    }
}

这里重点是:每加一段路径,就立刻设置对应颜色,然后填充,这样每段都是独立的,交替颜色自然就出来了。

3. 视图属性没设置对

要是你的视图默认背景色和绘制颜色一样,或者opaque属性没设对,也会看起来没显示。可以在初始化方法里加几句:

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = .clear // 避免和绘制颜色冲突,也可以设你要的背景色
    self.isOpaque = false // 要是有透明区域的话,必须设成false
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.backgroundColor = .clear
    self.isOpaque = false
}

4. 没处理上下文为空的情况

一定要加guard let ctx = UIGraphicsGetCurrentContext() else { return },要是上下文拿不到,后面的代码全白跑了,自然啥也画不出来。

补几个CG绘制的小提醒
  • 坐标系:CG默认原点在左下角,但在draw(_ rect:)方法里,系统已经帮你把上下文坐标系转换成UIKit的左上角了,所以直接按UIKit的坐标逻辑画就行,不用自己转。
  • 状态保存:要是你需要临时改状态(比如换线条宽度),记得用ctx.saveGState()保存当前状态,改完之后用ctx.restoreGState()恢复,不然会影响后面的绘制。
  • 性能优化:要是你的视图需要频繁刷新,最好把路径缓存起来,别每次draw都重新计算路径,能省不少性能。

内容的提问来源于stack exchange,提问作者user5336403

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:47:34