Установка правильного кадра вновь созданного CAShapeLayer - PullRequest
16 голосов
/ 29 декабря 2011

Короче говоря:

  1. Apple НЕ устанавливает frame или bounds для CAShapeLayer автоматически (а Apple НЕ ИСПОЛЬЗУЕТ эквивалент [UIView sizeThatFits])
  2. Если вы устанавливаете кадр, используя размер ограничивающего прямоугольника пути ... все идет не так. Независимо от того, как вы пытаетесь установить его, он запутывает путь

Итак, как правильно программно установить кадр вновь созданного CAShapeLayer с добавленным CGPath? Документы Apple молчат по этому поводу.

Вещи, которые я пробовал, которые не работают:

  1. Создать CAShapeLayer
  2. Создайте CGPath, добавьте его в слой
  3. Проверьте слой frame - это {{0,0},{0,0}}
  4. Набор: layer.frame = CGPathGetBoundingBox( layer.path )
  5. Кадр теперь правильный, но путь теперь сдвоенный - смещение frame приводит к эффективному смещению пути на дополнительные (x,y) пикселей

  6. Набор: layer.bounds = CGPathGetBoundingBox( layer.path )

  7. ... все сходит с ума. Ничто больше не имеет смысла
  8. Попробуйте исправить это, выполнив layer.position = CGPathGetBoundingBox( layer.path ).origin
  9. ... без кубиков; все еще орехи.

Одна вещь, которую я пробовал, ДЕЙСТВИТЕЛЬНО работает, но вызывает проблемы в других местах:

РЕДАКТИРОВАТЬ: это ломается, как только вы автоматически поворачиваете экран. Мое предположение: для автоповорота Apple требуется контроль над свойством transform.

  1. Создать CAShapeLayer
  2. Создайте CGPath, добавьте его в слой
  3. Проверьте рамку слоя - это {{0,0},{0,0}}
  4. Набор: layer.frame = CGPathGetBoundingBox( layer.path )
  5. Набор: layer.transform = CGAffineTransformMakeTranslation( CGPathGetBoundingBox( layer.path ).origin.x * -1, // same for y-coord: set it to "-1 * the path's origin

Это работает, но ... многие сторонние коды предполагают, что начальное преобразование для CALayer - это Identity.

Это не должно быть так сложно! Конечно, я что-то здесь не так делаю?

(у меня было одно предложение: «каждый раз, когда вы добавляете путь, вручную запускайте пользовательскую функцию, чтобы сместить все точки на -1 * (top-left-point.x, top-left-point.y)». Опять же, это работает - но это до смешного сложно)

1 Ответ

5 голосов
/ 11 декабря 2013

Установка layer.bounds для границ пути - правильная вещь - вы хотите, чтобы локальное пространство координат слоя соответствовало пути.Но тогда вам также необходимо установить свойство position слоя, чтобы переместить его в нужное место в его суперслое.

(Настройка .frame переводит в каркас, вычисляя правильные значения .bounds и .position для вас, ноон всегда оставляет bounds.origin нетронутым, а это не то, что вам нужно, когда границы вашего пути имеют ненулевое начало.)

Так что-то вроде этого должно работать, предполагая, что вы не изменили anchorPoint от его обычного(.5, .5) и хотите поместить слой вровень с началом его суперслоя:

CGRect r = CGPathGetBoundingBox(layer.path);
layer.bounds = r;
layer.position = CGPointMake(r.size.width*.5, r.size.height*.5);
...