Swift 中的自定义 UI 元素:子类化 CALayer 并覆盖 drawInContext 导致像素化绘图
Posted
技术标签:
【中文标题】Swift 中的自定义 UI 元素:子类化 CALayer 并覆盖 drawInContext 导致像素化绘图【英文标题】:Custom UI element in Swift: Subclassing CALayer and overriding drawInContext results in pixelated drawing 【发布时间】:2014-11-15 12:07:48 【问题描述】:我目前正在学习如何实现自定义控件。我不可避免地偶然发现了 CALayer 的可能性,因为当需要执行复杂的动画时,使用 UIImage 不够灵活。
我想将 UIView 用作 CALayer 的“容器”,以便它的宽度和高度始终与 UIView 相同(出于灵活性目的)。
我继承了 CALayer 并覆盖了 drawInContext() 方法。
这是我在屏幕上看到的结果:
绘图看起来像素化和模糊。我正在使用 PaintCode 为我生成绘图代码。
这是自定义的 CALayer:
class SegmentActive: CALayer
func frameSetup() -> CGRect
let frameWidth:CGFloat = superlayer.frame.width
let frameHeight:CGFloat = superlayer.frame.height
let frame = CGRectMake(0, 0, frameWidth, frameHeight)
println("\(superlayer.frame.width) // \(superlayer.frame.height)")
return frame
override func drawInContext(ctx: CGContext!)
UIGraphicsPushContext(ctx)
CalorieCalculatorUI.drawSegControlActiveBase(frameSetup())
UIGraphicsPopContext()
我是这样使用它的:
class ViewController: UIViewController
@IBOutlet weak var leftSegmentUIView: UIView!
override func viewDidLoad()
let activeSegment:SegmentActive = SegmentActive()
leftSegmentUIView.layer.addSublayer(activeSegment)
activeSegment.frame = activeSegment.frameSetup()
activeSegment.setNeedsDisplay()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
我在这里做错了什么? :(
【问题讨论】:
【参考方案1】:tl;dr:您必须将图层的contentsScale
设置为大于默认值 1.0 的值。
图层的比例因子默认为 1。这会更改该图层的内容缓冲区的大小:
适用于 [...] 和通过
-drawInContext:
提供的内容(即,如果contentsScale
是两个-drawInContext:
将绘制到两倍于层边界的缓冲区中)
由于您在像素比设备屏幕少的上下文中进行自定义绘图,因此绘图看起来像素化。对于传统的“视网膜”屏幕,您所期望的比例因子是2.0
,但随着最近推出的 iPhone 6+ 的推出,还有 3.0
的比例因子。好消息是您可以从UIScreen
获取设备规模。
【讨论】:
非常感谢大卫!你是绝对的传奇!你的答案和博客总是充满了知识和智慧。再次感谢您好心的先生! 确实如此。只是 FTR 一个常见的、类似的、相关的问题是,当您(比如说)为类似的大小设置动画时,您需要 self.layer.shouldRasterize = YES; 嘿@JoeBlow,谢谢!我确实计划为很多东西制作动画,所以我相信它会派上用场。 我真的希望它有所帮助。我有时会因为忘记这一点而浪费时间!!以上是关于Swift 中的自定义 UI 元素:子类化 CALayer 并覆盖 drawInContext 导致像素化绘图的主要内容,如果未能解决你的问题,请参考以下文章
想知道如何以编程方式在 swift 3.0 中对 UITableViewCell 进行子类化?
Appium 自动化测试:如何从 android [android.view.View] 中的自定义 UI 中获取元素或文本