Как сохранить постоянную CGLayerRef даже после переключения ориентации устройства? - PullRequest
3 голосов
/ 19 февраля 2012

Я использую CoreGraphics, чтобы иметь CGLayerRef, который я храню в переменной.

Я рисую пути в CGLayerRef вне экрана, а затем, когда мне нужно, я рендеринг. Это прекрасно работает, потому что я рисую много путей, и это помогает с производительностью.

Проблема возникает при изменении ориентации iPad. Когда это происходит, мне нужно сохранить свои рисунки в CGLayerRef без каких-либо изменений, несмотря на то, что кадр изменился. Я не хочу перерисовывать все внутри, потому что это будет очень медленно.

Итак ... как я буду держать это, как это было в предыдущей ориентации?

Подводя итог в картинках:

Это моя нормальная портретная ориентация: enter image description here

И когда ориентация меняется, моя цель состоит в том, чтобы она выглядела примерно так: enter image description here

Заранее спасибо,

-Давид

Ответы [ 2 ]

1 голос
/ 28 февраля 2012

Если вы не хотите, чтобы ориентация интерфейса изменялась, просто закомментируйте метод shouldAutorotateToInterfaceOrientation в вашем контроллере представления.

1 голос
/ 21 февраля 2012

Звучит так, будто вы хотите, чтобы представление всегда отображало его содержимое в одной и той же ориентации относительно устройства , независимо от ориентации интерфейса (строка состояния и т. Д.). Так что на ваших изображениях, если «привет» рисуется с помощью «h» с помощью кнопок физической громкости, то вы всегда хотите, чтобы «h» рисовали с помощью кнопок физической громкости, даже если пользователь повернул устройство (и остальные пользовательский интерфейс повернулся).

iOS вращает пользовательский интерфейс, устанавливая преобразование представления вашего корневого контроллера. Вы можете проверить это в отладчике:

# Unrotated
(lldb) po [[(id)UIApp keyWindow] recursiveDescription]
(id) $1 = 0x0b535030 <UIWindow: 0xd434a80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd434b70>>
   | <UIView: 0xb5385e0; frame = (0 20; 320 460); autoresize = W+H; layer = <CALayer: 0xb538710>>

# Rotated with home button at the left
(lldb) po [[(id)UIApp keyWindow] recursiveDescription]
(id) $2 = 0x0f036060 <UIWindow: 0xd434a80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd434b70>>
   | <UIView: 0xb5385e0; frame = (20 0; 300 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xb538710>>

Таким образом, вы можете отменить это, применив обратное преобразование к вашему графическому контексту, прежде чем рисовать ваш контент. Но вы также должны скорректировать происхождение вашего графического контекста, что делает его немного хитрее.

Во-первых, вам нужно переместить начало координат в центр вида. Затем вы применяете обратное преобразование, чтобы отменить поворот интерфейса. Затем вы перемещаете источник назад. Предполагая, что ваш CGLayer имеет тот же размер, что и ваш вид (в портретной ориентации), это должно работать:

- (void)drawRect:(CGRect)rect
{
    if (!_cgLayer) {
        [self initCGLayer];
    }

    CGContextRef gc = UIGraphicsGetCurrentContext();
    CGContextSaveGState(gc); {
        CGSize mySize = self.bounds.size;
        CGSize cgLayerSize = CGLayerGetSize(_cgLayer);
        CGContextTranslateCTM(gc, mySize.width / 2, mySize.height / 2);
        CGContextConcatCTM(gc, CGAffineTransformInvert(self.window.rootViewController.view.transform));
        CGContextTranslateCTM(gc, -cgLayerSize.width / 2, -cgLayerSize.height / 2);
        CGContextDrawLayerAtPoint(gc, CGPointZero, _cgLayer);
    } CGContextRestoreGState(gc);
}

Это не идеально. Это заканчивается рисованием, как я сказал: всегда в той же ориентации относительно устройства. Однако из-за способа поворота интерфейса пользователь поворачивает устройство, он перерисовывает изображение, повернутое на 90 градусов, и поворачивает изображение в правильную ориентацию.

Я поместил тестовый проект здесь:

https://github.com/mayoff/stackoverflow-cglayer-unrotating

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

...