Порядок наложения iPhone CALayer

Я использую CALayers для рисования в UITableViewCell. Я пытаюсь выяснить, как слои упорядочены с содержимым UITableViewCell. Например:

  1. Я добавляю метки в UITableViewCell в методе cellForRow:atIndexPath.
  2. В методе drawRect UITableViewCell я рисую некоторый контент, используя текущий контекст
  3. Также в drawRect я добавляю несколько подслоев

Итак, каков будет порядок этих элементов. Я знаю, что у меня есть zPosition на CALayers, но я не уверен, что они всегда находятся поверх каких-либо подпредставлений UITableViewCell. И я не уверен, в каком порядке находится содержимое, отрисовываемое в drawRect. Любая помощь или ссылки на документацию были бы замечательными. Я прочитал Руководство по программированию основной анимации и нигде не нашел, где на этот вопрос можно было бы ответить.


person Brian    schedule 31.03.2010    source источник


Ответы (2)


  1. Ваш UITableViewCell (или производный класс) является производным от UIView. Он владеет одним CALayer, к которому вы можете получить доступ через свойство слоя. Этот слой занимает всю область просмотра. UILabels, которые вы добавляете в представление своей ячейки, будут дочерними элементами UIView вашей ячейки, а их CALayer будет дочерним элементом CALayer ячейки. Дочерние слои рисуются перед их родителями.
  2. Когда вы рисуете что-либо в методе drawRect UIView, CALayer, которым владеет UIView, будет поддерживаться растровым изображением. Ваши UILabels будут частично или полностью скрывать это растровое изображение в зависимости от их размера.
  3. Любые дочерние CALayers, которые вы добавите к слою вашей ячейки позже, будут родственными слоями UILabel, и, поскольку вы добавили их позже, они будут добавлены под ними по умолчанию (существуют версии метода, который добавляет их, которые могут управлять порядком).

Обратите внимание, что рисование в UITableViewCell и одновременное использование дочерних представлений не рекомендуется по соображениям производительности. По той же причине не рекомендуется иметь более 4 дочерних представлений/слоев.

person U62    schedule 31.03.2010
comment
Таким образом, порядок видимости будет следующим: снизу вверх: растровое изображение фона UITableViewCell — UITableViewCell.layer — растровое изображение фона UILabel — UILabel.layer? Если это так, то UILabel.layer является подуровнем UITableViewCell.layer? - person Brian; 31.03.2010

CALayers поддерживают иерархию, как и представления. Подслои отображаются перед своим суперслоем, все вверх по иерархии. Свойство zPosition следует использовать только для управления визуализацией одноуровневых слоев путем размещения одного над другим. Даже в этом случае предпочтительно упорядочивать одноуровневые слои в свойстве sublayers (слои рисуются в том порядке, в котором они находятся в этом массиве, при этом каждый последующий слой рисуется на предыдущем в массиве).

Эту иерархию довольно легко увидеть, потому что вы вручную добавляете подслои к слою, когда создаете их в своем коде, вплоть до уровня поддержки для вашего UITableViewCell (подкласс поддерживаемого слоями UIView).

Кроме того, вам действительно не следует добавлять слои в свой UITableViewCell в его методе -drawRect:. Это следует использовать только для рисования содержимого базового слоя UITableViewCell. Выделение и настройка CALayers в этом методе может привести к значительному замедлению при прокрутке или перерисовке. Вам нужно настроить эти слои только один раз в какой-то момент при инициализации UITableViewCell, а затем просто обновить их по мере повторного использования ячейки.

person Brad Larson    schedule 31.03.2010
comment
Мне любопытно, где правильно построить иерархию слоев? Допустимо ли для UITableViewController добавлять подслои в UITableViewCell.layer? У меня есть два слоя: один — это фон ячейки, нарисованной с помощью CGGradient, а другой — слой, который появится над UITableViewCell. Из ответа U62 кажется, что я должен просто нарисовать градиент в ячейке. Я делал это раньше, но изменил его на слой, потому что слышал кеш слоев. Градиент полупрозрачный, чтобы выглядеть как глянец, но прокрутка дергается. - person Brian; 31.03.2010
comment
Я забыл - я также пытался нарисовать градиент и сохранить его как CGImage в layer.contents. Но когда я запускаю Core Animation в Instruments, он показывает, что градиент все еще смешивает цвета. - Спасибо за вашу помощь. - person Brian; 31.03.2010
comment
@Brian: Слои кэшируются, но ваши представления поддерживаются слоями. Если вы не перерисовываете градиент каждый раз, когда ячейка табличного представления повторно используется, ваш градиент не будет перерисовываться, если вы просто нарисуете его в фоновом режиме в Quartz. Однако, если вы ищете высокопроизводительную реализацию градиентов, вы можете проверить пример CAGradientLayer Мэтта Галлахера: cocoawithlove.com/2009/08/ - person Brad Larson; 31.03.2010
comment
@Brian: Если у вас есть несколько слоев, они будут компоноваться на графическом процессоре каждый раз, когда что-то анимируется на экране, поэтому Apple рекомендует сглаживать представление или иерархию слоев, чтобы сгладить прокрутку. Я считаю, что они предоставляют пример приложения для этого. - person Brad Larson; 31.03.2010