2013-08-27 3 views
28

В documentation Apple, говорится, что вы должны учитывать коэффициент масштабирования слоя, когда он:Когда мне нужно установить свойство contentsScale CALayer?

  • создает дополнительные слои Core Animation с различными масштабными коэффициентами и композитов их в свое собственное содержание
  • Устанавливает содержание свойство слоя Core Animation непосредственно

Последнее утверждение не совсем ясно для меня. Они также говорят:

Приложения, использующие внутренние слои анимации непосредственно для обеспечения контента может потребоваться настроить свой код рисования для учета масштаба факторов. Обычно, когда вы рисуете метод drawRect: view или в методе drawLayer: inContext: метод делегата слоя, система автоматически настраивает графический контекст для учета для шкал факторов.

Нормально или всегда? и это справедливо только для поддерживаемого слоя представления или каждого слоя, который я добавляю в качестве подслоя для слоя подложки? потому что они также говорят:

Если ваше приложение создает слои без соответствующей точки зрения, масштабный коэффициент для каждого нового слоя объекта установлен в 1,0 изначально. Если вы не измените этот масштабный коэффициент , и если впоследствии вы нарисуете слой на экране с высоким разрешением , содержимое слоя автоматически масштабируется , чтобы компенсировать разницу в масштабных коэффициентах. Если вы не хотите, чтобы содержимое масштабировалось, вы можете изменить масштабный коэффициент слоя на 2.0, но если вы сделаете это без предоставления контента с высоким разрешением, ваш существующий контент может оказаться меньше, чем вы ожидали. Чтобы исправить ошибку , вам необходимо предоставить контент с более высоким разрешением для вашего слоя .


У меня возникли трудности, представляя себе слой без зрения, я могу себе представить иерархию слоев, но как только я хочу показать им, что я должен добавить его в качестве subhierachy отступающего слоя зрения, либо существуют ли какие-то другие средства для их использования (например, создание и просто рецензирование в контексте)?

Ядро композитинга двигатель Animation выглядит на свойство каждого слоя contentsScale определить содержимое этого слоя нужно ли масштабировать во время композитинга. Если ваше приложение создает слоев без соответствующего вида, каждый масштаб объекта будет иметь значение 1.0. Если вы не измените этот масштабный коэффициент , и если впоследствии вы нарисуете слой на экране с высоким разрешением , содержимое слоя будет автоматически масштабировано для компенсации за разницу в масштабных коэффициентах. Если вы не хотите, чтобы содержимое масштабировалось, вы можете изменить масштабный коэффициент слоя на 2.0, но если вы делаете это без предоставления контента с высоким разрешением, то существующий контент может оказаться меньше, чем вы ожидали. Чтобы исправить эту проблему , вам необходимо предоставить контент с более высоким разрешением для вашего слоя.

Что это значит? Когда я делаю что-то подобное layer.contents = (id)image.CGImage Мне нужно установить contentsScale.
Должен ли я также установить его, когда мой слой рисует его содержимое, вызывая метод делегата drawLayer:inContext:, а слой не является поддерживающим слоем представления?

+0

В случае ** iOS ** это подробно объясняется здесь: https://stackoverflow.com/a/ 47760444/294884 и здесь: https://stackoverflow.com/a/47778332/294884 Надеюсь, это поможет кому-то. – Fattie

ответ

14

Re: Содержание слоя с помощью -drawRect: или -drawLayer: InContext:

Normallly или всегда? и это справедливо только для поддерживаемого слоя представления или каждого слоя. Я добавляю в качестве подслоя для слоя подложки?

Всегда. Когда эти методы вызывают, в текущем контексте уже будет применен коэффициент масштабирования. Например, если ваш слой равен 10pt x 10pt, он имеет границы {0,0,10,10}, независимо от содержимогоScale. Если contentsScale = 2 (например, вы находитесь на сетчатке), это фактически 20x20 пикселей. CALayer уже настроит хранилище 20x20px и применит масштабный коэффициент CGContextScaleCTM (контекст, 2, 2).

Это так, что вы можете сделать свой рисунок в своем концептуальном пространстве 10x10 в любом случае, но резервное хранилище удваивается, если пиксели удваиваются.

У меня возникли трудности, представляя себе слой без зрения, я могу себе представить иерархию слоев, но как только я хочу показать им, что я должен добавить его в качестве subhierachy отступающего слоя зрения, либо существуют какие-то другие способы их использования (например, создание и просто renderring в контексте)?

Вы можете создать их, добавьте их в качестве подслоя, и либо установить их делегата на объект, где вы реализуете -drawLayer: InContext :, или вы можете непосредственно установить содержимое слоя. В iOS UIView является довольно мелкой оболочкой вокруг CALayer, поэтому обычно имеет смысл создавать subviews вместо прямого создания подслоев, поэтому вы не знакомы с этим использованием. В OS X, NSW с поддержкой слоев - большая и сложная оболочка вокруг CALayer, поэтому имеет смысл сделать целые иерархии слоев в пределах одного представления.

Что это значит? Когда я делаю что-то вроде этого layer.contents = (id) image.CGImage Мне нужно установить contentsScale.

Да. Но то, что этот отрывок в документации говорит вам, заключается в том, что если вы хотите не выглядеть уродливым, то 10pt x 10pt-слой с содержимымScale 2, нуждается в содержимом 20px x 20px. То есть Вы должны обратить внимание на contentsScale слоя, когда вы непосредственно устанавливаете содержимое слоя, если хотите избежать масштабирования артефактов. InContext:: а слой не подкладочный слой зрения

Мне также нужно установить его, когда мой слой рисует это содержание вызова метод делегата drawLayer ли?

Да. Если вы сами создаете слои (не создаваемые с помощью UIView), вам необходимо установить их масштаб вручную. Обычно это просто layer.contentsScale = [[UIScreen mainScreen]]. (Опять же, на OS X это немного сложнее, так как экраны могут приходить и уходить во время работы.)

+0

Спасибо за подробный ответ! Если A и B являются обоими слоями слоя Z, нужно ли устанавливать слой Z также для содержимого contentsScale или не имеет значения contentsScale родителя? – Crashalot

5

На OS X вы в основном

  1. захватить ваше окно -backingScaleFactor
  2. набора каждый (!) Слой -contentsScale к этому scaleFactor
  3. реализовать -layer:shouldInheritContentsScale:fromWindow: в контроллере
  4. набора каждого слой -delegate к этому контроллеру

Я знаю, что это за wned здесь, на SO, чтобы просто ссылаться на внешний URL, но это сложно описать. Вот код, который работает правильно для меня в отношении масштабных факторов:

https://github.com/JanX2/ScrollingAboutWindow

Надежда, что помогает.

+0

Было бы правильным альтернативным решением установить слой (или слои) слоя 'contentsScale' из 'viewDidChangeBackingProperties' (или' windowDid ... ')? –

+0

Идея. AFAIK, это то, как Apple советует вам использовать. – JanX2

5

Хотя слой почти всегда используется внутри представления, этот слой, возможно, был создан ad-hoc и добавлен в качестве подуровня слоя вида или назначается в качестве маски другого слоя. В обоих случаях необходимо установить свойство contentsScale. Например:

UIView *myMaskedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
CALayer *myMaskLayer = [CALayer new]; 
myMaskLayer.frame = myMaskedView.bounds; 
UIImage *maskImage = [UIImage imageNamed:@"some_image"]; 
myMaskLayer.contents = (id)maskImage.CGImage; 
myMaskLayer.contentsScale = maskImage.scale; 
myMaskedView.layer.mask = myMaskLayer; 

Вы также можете построить иерархию слоев для выполнения анимации без использования каждого слоя обратно вид:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 

CALayer *sublayerA = [CALayer new]; 
sublayerA.contentsScale = myView.layer.contentsScale; 
[myView.layer addSublayer:sublayerA]; 

CALayer *sublayerB = [CALayer new]; 
sublayerB.contentsScale = myView.layer.contentsScale; 
[myView.layer addSublayer:sublayerB]; 

// Continue adding layers 

Это особенно важно для Retina устройств, которые имеют собственный экран масштаба 2,0; слой со шкалой по умолчанию 1.0 будет отображать заметную пикселизацию.

+0

Aha! Это не относится к тем слоям, которые создает один из них, объясняет, почему в моем размещенном слое для моего Mac-приложения не было правильного набора 'contentsScale'. Я полагаю, что если бы мой взгляд поддерживался с помощью слоя, а не на уровне хостинга, то он был бы настроен для меня по представлению (на уровне NSView), когда он создал свой слой. –

+0

Я думаю, что этот ответ и комментарий попали на вопрос, который у меня был, когда я читал этот вопрос: когда вы создаете слой, а затем добавляете его в иерархию уровней, прикрепленную к представлению, действие добавления слоя само не устанавливается Свойство contentScale к свойству экрана, правильно? – s73v3r

+1

Это правильно. Добавление слоя в иерархию представления не устанавливает его 'contentsScale'. – Austin

Смежные вопросы