2014-09-21 2 views
2

В настоящее время я изучаю, как реализовать пользовательские элементы управления. Я неизбежно наткнулся на возможность CALayer, поскольку использование UIImage недостаточно гибко, когда необходимо выполнить сложные анимации.Пользовательский элемент пользовательского интерфейса в Swift: подклассификация CALayer и переопределение drawInContext приводит к пиксельному рисунку

Я хочу использовать UIView как «контейнер» для CALayer, так что его ширина и высота всегда совпадают с UIView (для целей гибкости).

Я подклассифицировал 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

Большое спасибо Давиду! Ты абсолютная легенда! Ваши ответы и блоги всегда наполнены знаниями и мудростью. Еще раз - спасибо добрый сэр! –

+1

Действительно. Просто FTR общие, похожие, связанные проблемы: когда вы (скажем) оживляете размер чего-то подобного, вам нужно self.layer.shouldRasterize = YES; – Fattie

+0

Эй, @ JoeBlow, спасибо! Я действительно планирую оживить много вещей, поэтому я уверен, что это пригодится. –