2014-09-21 52 views
2

我目前正在学习如何实现自定义控件。我不可避免地偶然发现了CALayer的可能性,因为当需要执行复杂的动画时,使用UIImage并不够灵活。我想使用UIView作为CALayer的“容器”,以使它的宽度和高度总是与UIView相同(为了灵活性)。Swift中的自定义UI元素:继承CALayer并重写drawInContext结果pixelated drawing

我分类了CALayer并覆盖了drawInContext()方法。

这里是我得到屏幕上的结果: Fuzzy/Pixelated image

图纸看起来像素化和模糊。我正在使用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. 
} 

}

我在做什么错在这里? :(

回答

6

TL;博士:你必须设置图层的contentsScale的东西比默认1.0大


一层默认为1的比例因子这改变多大。该层的内容缓冲区是:

适用于[...]和内容经由-drawInContext:提供(即,如果contentsScale是二-drawInContext:将绘制到缓冲器中两倍大的层边界)

由于您正在执行具有比设备屏幕更少像素的上下文的自定义绘图,因此绘图看起来像素化。对于传统的“视网膜”屏幕,您期望的比例因子是2.0,但随着最近推出的iPhone 6+,还有比例因子3.0。好消息是您可以从UIScreen获得设备规模。

+0

非常感谢David!你是一个绝对的传奇!你的答案和博客总是充满知识和智慧。再次 - 谢谢你,先生! – 2014-09-21 12:40:53

+1

确实。就FTR而言,一个常见的,类似的相关问题是,当你(比如说)动画这样的东西的大小时,你需要self.layer.shouldRasterize = YES; – Fattie 2014-09-21 12:46:15

+0

嘿@JoeBlow,谢谢!我确实计划制作很多东西,所以我相信这会派上用场。 – 2014-09-21 13:10:18