创建带有圆角矩形的进度指示器

Posted

技术标签:

【中文标题】创建带有圆角矩形的进度指示器【英文标题】:Creating a progress indicator with a rounded rectangle 【发布时间】:2018-09-25 17:22:37 【问题描述】:

我正在尝试在我的应用程序中创建一个圆角矩形进度指示器。我之前实现了一个圆形指示器,但不喜欢这种形状。我希望它看起来像这样(起点在顶部):

但我将0 作为图层的.strokeStart 属性:

我当前的代码在viewDidLoad():

let queueShapeLayer = CAShapeLayer()
let queuePath = UIBezierPath(roundedRect: addToQueue.frame, cornerRadius: addToQueue.layer.cornerRadius)
queueShapeLayer.path = queuePath.cgPath
queueShapeLayer.lineWidth = 5
queueShapeLayer.strokeColor = UIColor.white.cgColor
queueShapeLayer.fillColor = UIColor.clear.cgColor
queueShapeLayer.strokeStart = 0
queueShapeLayer.strokeEnd = 0.5
view.layer.addSublayer(queueShapeLayer)

addToQueue 是显示“Upvote”的按钮。

与创建圆形进度指示器不同,我无法在 Bezier 路径的初始化中设置开始和结束角度。

如何让进度从第一张图片中的顶部开始?

编辑 - 添加一张没有圆角半径的图片:

似乎是圆角半径造成了问题。


如果您有任何问题,请提出!

【问题讨论】:

我建议不要在viewDidLoad 中进行所有设置,而是创建自定义UIView 子类。另外,如果您能提供minimal reproducible example @Cristik 如果我创建一个自定义的UIView 子类会有什么帮助,但我看不到任何好处?另外,我相信我的问题是最小的、完整的和可验证的。你能详细说明为什么不是吗? 对于初学者,问题中的代码无法编译。我们应该能够把代码扔到操场上。这会让人们更容易帮助你。 @Cristik 好的,我刚刚从程序的其他地方添加了第一行。谢谢 您在寻找动画吗?您的两个屏幕截图(以及您的问题中的其他内容)表明了这一点。我当然不是 CoreAnimation 方面的专家(这就是 CALayers 的意义所在),但 viewDidLoad 似乎是完全错误的地方。也许从一个更基本的例子开始?说一个矩形形状(不是cornerRadius)并让工作?我认为如果您使用draw(rect:) 和一个简单的矩形,那么让弯曲的边框工作将是一件简单的事情。 【参考方案1】:

我找到了一个解决方案,因此加载指示器适用于圆角:

let queueShapeLayer = CAShapeLayer()

override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)

    // Queue timer
    let radius = addToQueue.layer.cornerRadius
    let diameter = radius * 2
    let totalLength = (addToQueue.frame.width - diameter) * 2 + (CGFloat.pi * diameter)

    let queuePath = UIBezierPath(roundedRect: addToQueue.frame, cornerRadius: radius)
    queueShapeLayer.path = queuePath.cgPath
    queueShapeLayer.lineWidth = 5
    queueShapeLayer.strokeColor = UIColor.white.cgColor
    queueShapeLayer.fillColor = UIColor.clear.cgColor
    queueShapeLayer.strokeStart = 0.25 - CGFloat.pi * diameter / 3 / totalLength // Change the '0.25' to 0.5, 0.75 etc. wherever you want the bar to start
    queueShapeLayer.strokeEnd = queueShapeLayer.strokeStart + 0.5 // Change this to the value you want it to go to (in this case 0.5 or 50% loaded)
    view.layer.addSublayer(queueShapeLayer)

不过,在我这样做之后,我遇到了一些问题,我无法在整个过程中制作动画。为了解决这个问题,我创建了第二个动画(将strokeStart 设置为0),然后我放置了completion blocks,这样我就可以在正确的时间触发动画。

提示:

在使用CABasicAnimation 时添加animation.fillMode = CAMediaTimingFillMode.forwardsanimation.isRemovedOnCompletion = false 以使动画等到您将其删除。

我希望这个公式对以后的任何人都有帮助!

如果您需要帮助,可以随时给我发信息,我愿意提供帮助。 :)

【讨论】:

这是错误的。正确答案很简单。如果你想让路径从顶部中心开始,那么UIBezierPath(roundedRect: 太粗略了;您必须自己创建一条从顶部中心开始的路径。线,弧,线,弧,线。 @matt 你建议我应该使用什么? 天哪,我以为我刚刚在之前的评论中告诉过你:“你必须自己创建一条从顶部中心开始的路径”。 @matt 我现在只是在看路径,我以前从未使用过它们。谢谢:)

以上是关于创建带有圆角矩形的进度指示器的主要内容,如果未能解决你的问题,请参考以下文章

Android自定义圆角矩形进度条2

带有圆角矩形的 SKScene

带有透明圆角矩形的 UIView?

从带有圆角的矩形中检测角点

Android UI绘制圆角矩形进度条 ① ( 像素值转化 dp -> px | Paint 标志位设置 | Paint 画笔线帽样式设置 | Paint 画笔线段连接处样式设置 )

将标签绘制为带有边缘而不是圆角的矩形