我有一个循环的 UIBezierPath 和 2x CAShapeLayers,我用它来显示我的一个应用程序中特定里程碑的进度。
问题:当我通过 CABasicAnimation 为进度设置动画时,进度超出了它应该做的事情。
上下文: 我在 milestonesCollectionView 内的自定义单元格的 subview 中显示此 circularView。
View Hierarchy:CollectionView > Custom Cell > subview > drawRect 以在其中创建和添加图层。
我的代码:
自定义单元格
在我的自定义单元格中,我设置了 currentProgress(为了测试目的而硬编码)
let placeHolderForProgressView: CircularTrackerView = {
let ctv = CircularTrackerView()
ctv.backgroundColor = UIColor.clear
ctv.translatesAutoresizingMaskIntoConstraints = false
ctv.currentProgress = 0.5 //set to 0.5 to get a circle filled at 50%
return ctv
}()
内部 CircularTrackerView
//每当设置单元格并向 progressView 提供 currentProgress 时,我都会为进度设置动画
var currentProgress: CGFloat = 0.0 {
didSet {
animate(to: currentProgress)
let percent = Int(currentProgress * 100)
percentLbl.text = "\(percent)%"
}
}
let shapeLayer = CAShapeLayer() //displays the progress
let trackLayer = CAShapeLayer() //background of the ring
override func draw(_ rect: CGRect) {
super.draw(rect)
let center = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.white.withAlphaComponent(0.2).cgColor
trackLayer.lineWidth = 5
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = kCALineCapRound
layer.addSublayer(trackLayer)
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = UIColor.white.cgColor
shapeLayer.lineWidth = 5
shapeLayer.strokeEnd = 0
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineCap = kCALineCapRound
layer.addSublayer(shapeLayer)
}
private func animate(to progress: CGFloat) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0.0
animation.toValue = progress
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
shapeLayer.add(animation, forKey: "randomString")
}
输出
圆圈超出了 50% 的标记……甚至很难我认为我按照正确的步骤创建了这个(略微改编自 YouTube 上的 LetsBuildThatApp 教程:https://www.youtube.com/watch?v=O3ltwjDJaMk)
如果您能提供任何有用的意见,请提前致谢。
最佳答案
问题是你的 UIBezierPath/你给它的角度:
let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
endAngle - startAngle 的区别是 2.5 * PI 但应该仅为 2 * PI。当它是 2.5 * PI 时,这意味着 0.5 的 strokeEnd 导致 1.25 * PI 被描边。
解决方法,将endAngle减小0.5 * PI:
let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -0.5 * CGFloat.pi, endAngle: 1.5 * CGFloat.pi, clockwise: true)
关于ios - 圆形 BezierPath 相对于给定的进度值填充太多 - iOS Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48852681/
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
基本上,我只是试图在满足特定条件时停止程序运行其余行。unlessraw_information.firstputs"Noresultswerereturnedforthatquery"breakend然而,在程序运行之前我得到了这个错误:Invalidbreakcompileerror(SyntaxError)执行此操作的正确方法是什么? 最佳答案 abort("Noresultswerereturnedforthatquery")unlesscondition或unlessconditionabort("Noresultswer
我正在尝试解决http://projecteuler.net/problem=1.我想创建一个方法,它接受一个整数,然后创建一个包含它前面的所有整数的数组,并将整数本身作为数组中的值。以下是我目前所拥有的。代码不起作用。defmake_array(num)numbers=Array.newnumcount=1numbers.eachdo|number|numbers 最佳答案 (1..num).to_a是您在Ruby中需要做的全部。1..num将创建一个Range对象,以1开始并以任意值num结束是。Range对象有to_a方法通过
如果我想要“00001”而不是“1”,除了我自己写填零方法之外,有没有内置的方法可以帮助我为整数填零? 最佳答案 puts"%05d"%1#00001参见:String::%,Kernel::sprintf这是正在发生的事情。%左侧的"%05d"是C风格的格式说明符。%右边的变量就是要格式化的东西。格式说明符可以像这样解码:%-格式说明符的开头0-用前导零填充5-长度为5个字符d-被格式化的是一个整数如果你要格式化多个东西,你会把它们放在一个数组中:"%d-%s"%[1,"One"]#=>1-one
我在Ruby程序中有两个URI。一个肯定是绝对URI,另一个可能是绝对URI或相对URI。我想在第一个的上下文中将第二个转换为绝对URI,所以如果第一个是http://pupeno.com/blog第二个是/about,结果应该是http://pupeno.com/about.有什么想法吗? 最佳答案 Ruby的内置URI和Addressablegem,做这个简短的工作。我更喜欢Addressable,因为它功能更全面,但URI是内置的。require'uri'URI.join('http://pupeno.com/blog','/