Основная графика на дисплее Retina с 3D-преобразованием

Итак, кажется, я задаю трудные вопросы, но вот опять.

У меня, кажется, странная проблема. В некоторых представлениях я скрываю панели инструментов вверху, поворачивая их назад по оси x на 90 градусов. Затем я разрешаю пользователю «опускать» их, что повернет вид на 0 градусов, отображая панель инструментов. Все отлично работает, за исключением одного вида, где у меня есть две панели инструментов, которые нужно опустить. Это работает путем поворота первой панели инструментов вниз, а затем второй, при этом первая панель инструментов смещается вниз на высоту второй панели инструментов. Все это прекрасно работает на дисплеях без ретина. Однако на дисплее сетчатки смещение первой панели инструментов вдвое меньше, чем должно быть. Кроме того, рамка представления именно такая, какой она должна быть. Другими словами, когда я проверяю (NSLog), я получаю кадр {0, 30, 320, 30}, но фактическое изображение отображается в кадре: {0, 15, 320, 30}. Меняется только фон. Если я нажму на место, где должно быть представление, пройдут события касания.

Вот что происходит на экранах Retina:

введите здесь описание изображения

Вот что происходит на экранах без Retina (тот же код):

введите здесь описание изображения

Это код, который я использую для поворота представления (очень просто):

- (void) rotateView:(UIView *)view downBy:(CGFloat)rad{
    CALayer *rLayer = view.layer;
    CGFloat zDist = self.view.window.bounds.size.height * 1.5f;
    CATransform3D rT = CATransform3DIdentity;
    rT.m34 = 1.0f /  -zDist;
    rT = CATransform3DRotate(rT, rad, 1.0f, 0.0f, 0.0f);
    rLayer.transform = rT;
}

Опять же, это происходит только на дисплеях Retina.

Теперь панель инструментов отображается в Core Graphics. Поэтому я устранил свой CG-код как источник проблемы, полностью удалив его из drawRect, чтобы вообще не было никакого кода в draw rect; проблема все еще возникает. Я также заметил, что если я не использую drawRect (закомментируйте весь метод), вращение происходит правильно, но все подпредставления (которые также используют основную графику) отображаются с разрешением 1/2, так что все выглядит размытым:

введите здесь описание изображения

Я думаю, что это как-то связано с преобразованием, но я не уверен, как и почему. Если я установлю преобразование слоя в идентичность после того, как вращение вернется к 0 радианам (чтобы оно было полностью в поле зрения), вид привяжется к своему правильному положению. Я также заметил, что при 0 радианах трансформация не совсем идентична: m34 (перспектива) все еще установлена. Установка его на ноль решает проблему. Но установка его на ноль во время не решает проблему, пока вид находится в любом другом вращении, кроме 0 рад. А представления, которые не вращаются вниз от исходной точки {0,0}, все равно смещаются. Похоже, проблема возникает во время ЛЮБОГО 3D-преобразования, хотя я проверил все преобразования, чтобы подтвердить это.

ОБНОВЛЕНИЕ

Из-за ответа @Joshua Weinberg я начал возиться с rasterizationScale слоя. Я обнаружил, что смещение основного изображения было отключено на 1/rasterizationScale. Поэтому, если я установлю rasterizationScale на 6 и сдвину свой вид вниз на 30, фоновое изображение сдвинется только на 30/6 (5.0f).

ОБНОВЛЕНИЕ 2

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

rT = CATransform3DTranslate(rT, view.frame.origin.x - (view.frame.origin.x / rLayer.rasterizationScale), view.frame.origin.y - (view.frame.origin.y / rLayer.rasterizationScale), 0);

Выдает следующее: введите здесь описание изображения


person Aaron Hayman    schedule 21.03.2012    source источник


Ответы (2)


Я понял. Контроллер представления, с которым я боролся, находился в пользовательском контроллере контейнера, который я создал как собственный контроллер разделенного представления. Этот контроллер также использовал 3D-преобразования при переключении между панелями просмотра. В конце перехода я оставил .m34 (перспективное преобразование) в покое. Видимо, это было причиной всех проблем, которые у меня были. Я установил преобразование слоя в идентичность при переключении представлений в контроллере контейнера, и теперь все работает нормально.

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

person Aaron Hayman    schedule 21.03.2012

Установите rasterizationScale слоя на [[UIScreen mainScreen] scale], и он должен работать. Когда вы применяете 3D-преобразование, слой растеризуется, а растеризация по умолчанию — 1.0f;

person Joshua Weinberg    schedule 21.03.2012
comment
Нет, это не сработало, rasterizationScale уже было установлено на 2 по умолчанию на экранах сетчатки. Но это кажется частью проблемы. Если я установлю для параметра rasterizationScale значение 1.0f, все будет нормально работать с drawRect/Core Graphics, за исключением того, что изображение будет размытым. Если я не использую drawRect (только обычный вид), для rasterizationScale по умолчанию устанавливается значение 1. Если я вручную установлю его на 2, возникнут проблемы, описанные выше. - person Aaron Hayman; 21.03.2012