Чистые переходы авторотации в подкачке UIScrollView

У меня есть страница UIScrollView, в которой пользователь просматривает изображения по горизонтали, например Photos.app от Apple. Это работает, но теперь я пытаюсь добавить поддержку вращения.

У меня есть вращающийся вид, и мне удалось правильно установить contentSize, bounds и subviews фреймы, чтобы адаптироваться к различным ориентациям. Так что до и после ротации все ок.

Однако сами переходы неудобны. Первое изображение вращается идеально, как если бы ось вращения находилась в мертвой точке изображения (рамка scrollview). Второе изображение «качается», потому что ось вращения находится в том же месте: в центре первого изображения. Чем дальше я удаляюсь от первого изображения, тем быстрее "раскачивается".

Я, вероятно, смогу замаскировать это, наложив непрозрачный UIView перед вращением и скрыв его после. Но это взлом. Должен быть изящный способ сделать это ...


person alexantd    schedule 23.07.2010    source источник


Ответы (4)


Честно говоря, я не знаю, что вы делаете, потому что вы нам мало что показали.

Но!

Я создал образец проекта с несколькими представлениями в режиме прокрутки, и он отлично работает. Не стесняйтесь разбирать его, как хотите. Он работает, создавая 5 представлений и добавляя их в представление прокрутки. Затем, после того как эти представления настроены в первый раз, и каждый раз, когда приложение вращается, оно вызывает мой метод alignSubviews, чтобы разместить их в нужных местах страницы и сделать их того же размера, что и представление прокрутки, при обновлении contentSize представления прокрутки . Перед поворотом он отслеживает, на какой странице в данный момент находится вид прокрутки, а затем сбрасывает его на эту страницу во время поворота (поскольку размер страницы должен измениться).

Загрузите "Rotolling"!

скриншот

person jtbandes    schedule 28.07.2010
comment
Отличный пример! Я не публиковал код, потому что знал, что то, что у меня было, нужно выбросить. Мораль этой истории в том, что если я обнаруживаю, что вручную устанавливаю и сбрасываю рамки просмотра повсюду, я делаю это неправильно. - person alexantd; 29.07.2010
comment
Спасибо за отличный пример. Для успешного запуска на iOS 6 необходимо сделать одно исправление: [window setRootViewController: viewController]; приложению: метод didFinishLaunchingWithOptions. - person kaspartus; 16.11.2012
comment
Спасибо за отличный пример, который решил мою огромную проблему !! - person Cris; 15.12.2012

Я записываю эту дополнительную информацию для дальнейшего использования. Я решил это с помощью идеи из решения @jtvandes. Однако в моем случае этих реализаций хватило. Принудительный макет снова нарушил мой взгляд.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{
    currentPageOffset = [hostingScrollView contentOffset].x / [hostingScrollView bounds].size.width;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration 
{
    //  Layout changed instantly at this time.
    //  So we have to force to set offset instantly by setting animation to NO.
    [hostingScrollView setContentOffset:CGPointMake([hostingScrollView bounds].size.width * currentPageOffset, 0.0f) animated:NO];
}
person eonil    schedule 29.03.2011

Похоже, вы применяете магию, необходимую для вывода повернутой версии на экран в нужном месте, не так.

Поскольку вы не делились кодом, следующее предположение. Предположительно, вы применяете ротацию и перевод. Это звучит, как будто вы вращаете содержимое UIScrollView. Сделать это правильно будет непросто. Трудно сказать что-либо убедительное без кода, но если у вас есть только 1 поворот и 1 перевод, вы делаете это неправильно. Вам нужно перевести текущий вид в точку поворота, повернуть и перевести обратно. В противном случае перевод будет частью вращения (отсюда большой поворот).

Лучше поверните сам UIScrollView. Он всегда будет в определенном месте (а именно: на экране) с определенным центром. Затем содержимое будет вращаться вместе с ним.

person mvds    schedule 28.07.2010

Простое решение, которое хорошо работает, - это зарегистрироваться для получения уведомлений при изменении contentSize UIScrollView и затем обновить contentOffset в этот момент.

В методе загрузки вашего представления добавьте эту строку:

[self addObserver:theScrollView forKeyPath:@"contentSize" options:0 context:nil];

В методе разгрузки вашего представления добавьте эту строку:

[self removeObserver:self forKeyPath:@"contentSize"];

Лови уведомление:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    theScrollView.contentOffset = page * theScrollView.bounds.width;
}
person phatmann    schedule 01.06.2013