Как я сбрасываю после масштабирования UIScrollView?

16
задан Kampai 7 August 2014 в 17:58
поделиться

3 ответа

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

масштабирование представления является проблемой с UIScrollView, я столкнулся, все же. Во время масштабирующего повышение события, UIScrollView получит представление, что Вы указали в viewForZoomingInScrollView: метод делегата, и примените преобразование к нему. Это преобразование обеспечивает гладкое масштабирование представления, не имея необходимость перерисовывать его каждый кадр. В конце операции масштабирования Ваш метод делегата scrollViewDidEndZooming:withView:atScale: назовут и даст Вам шанс сделать более высококачественный рендеринг Вашего представления в новом масштабном коэффициенте. Обычно предложено сбросить преобразование на представлении, чтобы быть CGAffineTransformIdentity и затем иметь представление, вручную перерисовывают себя в новом масштабе размера.

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

Как обходное решение, я использую подкласс UIView для моего довольного представление со следующими определенными методами:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
    [super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
    [super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

, где previousScale является переменной экземпляра плавающей представления. Я затем реализую метод делегата изменения масштаба следующим образом:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    [contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
    contentView.previousScale = scale;
    scrollView.contentSize = contentView.frame.size;
}

Путем выполнения этого, преобразования, отправленные в довольное, представление корректируется на основе масштаба, в котором было в последний раз перерисовано представление. Когда изменение масштаба повышения сделано, преобразование сбрасывается к масштабу 1,0 путем обхода корректировки в нормальном setTransform: метод. Это, кажется, обеспечивает корректное поведение масштабирования, позволяя Вам привлечь четкое представление при завершении масштабирования.

ОБНОВЛЕНИЕ (7/23/2010): iPhone OS 3.2 и выше изменила поведение представлений прокрутки в отношении изменения масштаба. Теперь, UIScrollView будет уважать идентификационные данные, преобразовывают Вас, относятся к довольному представление и только обеспечивают фактор относительного масштаба в [1 110]. Поэтому вышеупомянутый код для UIView подкласс только необходим для устройств рабочие версии iPhone OS, более старые, чем 3,2.

43
ответ дан 30 November 2019 в 15:08
поделиться

I have a detailed discussion of how (and why) UIScrollView zooming works at github.com/andreyvit/ScrollingMadness/.

(The link also contains a description of how to programmatically zoom UIScrollView, how to emulate Photo Library-style paging+zooming+scrolling, an example project and ZoomScrollView class that encapsulates some of the zooming magic.)

Quote:

UIScrollView does not have a notion of a “current zoom level”, because each subview it contains may have its own current zoom level. Note that there is no field in UIScrollView to keep the current zoom level. However we know that someone stores that zoom level, because if you pinch-zoom a subview, then reset its transform to CGAffineTransformIdentity, and then pinch again, you will notice that the previous zoom level of the subview has been restored.

Indeed, if you look at the disassembly, it is UIView that stores its own zoom level (inside UIGestureInfo object pointed to by the _gestureInfo field). It also has a set of nice undocumented methods like zoomScale and setZoomScale:animated:. (Mind you, it also has a bunch of rotation-related methods, maybe we're getting rotation gesture support some day soon.)

However, if we create a new UIView just for zooming and add our real zoomable view as its child, we will always start with zoom level 1.0. My implementation of programmatic zooming is based on this trick.

5
ответ дан 30 November 2019 в 15:08
поделиться

Обратите внимание, что у решения, предоставленного Брэдом, есть одна проблема: если вы продолжаете программно увеличивать масштаб (скажем, при двойном касании) и позволяете пользователю вручную (уменьшать масштаб), после некоторого когда разница между истинным масштабом и масштабом, отслеживаемым UIScrollView, станет слишком большим, поэтому previousScale в какой-то момент выйдет за пределы точности с плавающей запятой, что в конечном итоге приведет к непредсказуемому поведению

2
ответ дан 30 November 2019 в 15:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: