Перерисовка содержимого UIScrollView после каждого увеличения - PullRequest
5 голосов
/ 23 июля 2010

У меня есть UIView внутри UIScrollView. Всякий раз, когда изменяется масштаб UIScrollView, я хочу перерисовать весь UIView на новом уровне масштабирования.

В iOS <3.2 я делал это, изменяя размер <code>UIView внутри UIScrollView, чтобы придать ему новый размер, а затем устанавливая преобразование обратно в Identity, чтобы оно не пыталось изменить его размер дальше. , Однако при iOS> = 3.2 изменение идентификатора также изменяет свойство zoomScale UIScrollView.

В результате каждый раз, когда я масштабирую (скажем, 2х), я настраиваю встроенный UIView на соответствующий размер и перерисовываю его. Однако теперь (так как я сбросил преобразование в Identity), UIScrollView снова думает, что его снова в zoomScale 1, а не zoomScale 2. Поэтому, если у меня установлено значение maxZoomScale в 2, оно все равно будет пытаться увеличить масштаб, что неправильно.

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

Кто-нибудь знает, как правильно перерисовать UIView на зум?

Ответы [ 2 ]

15 голосов
/ 03 октября 2010

Tom

Ваш вопрос немного устарел, но я нашел решение для этого, поэтому я решил ответить на случай, если он поможет вам или кому-то еще. Основной трюк состоит в том, чтобы сбросить zoomScale вида прокрутки на 1, а затем настроить minimumZoomScale и maximumZoomScale, чтобы пользователь мог все еще увеличивать и уменьшать масштаб, как и ожидалось.

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

Итак, мой метод init выглядит примерно так (kMinimumZoomScale и kMaximumZoomScale находятся наверху класса * 1014):

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.autoresizesSubviews = YES;
        self.showsVerticalScrollIndicator = YES;
        self.showsHorizontalScrollIndicator = NO;
        self.bouncesZoom = YES;
        self.alwaysBounceVertical = YES;
        self.delegate = self;

        self.minimumZoomScale = kMinimumZoomScale;
        self.maximumZoomScale = kMaximumZoomScale;
    }

    return self;
}

Затем я реализую стандартные UIScrollView методы делегирования для масштабирования. Мой класс ContentView имеет свойство zoomScale, которое сообщает ему, какой масштаб использовать для отображения его содержимого. Он использует это в своем методе drawRect для изменения размера содержимого соответствующим образом.

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
    return contentView;
}


- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale {
    CGFloat oldZoomScale = contentView.zoomScale;
    CGSize size = self.bounds.size;

    // Figure out where the scroll view was centered so that we can
    // fix up its offset after adjusting the scaling
    CGPoint contentCenter = self.contentOffset;
    contentCenter.x += size.width / (oldZoomScale * scale) / 2;
    contentCenter.y += size.height / (oldZoomScale * scale) / 2;

    CGFloat newZoomScale = scale * oldZoomScale;
    newZoomScale = MAX(newZoomScale, kMinimumZoomscale);
    newZoomScale = MIN(newZoomScale, kMaximumZoomscale);

    // Set the scroll view's zoom scale back to 1 and adjust its minimum and maximum
    // to allow the expected amount of zooming.
    self.zoomScale = 1.0;
    self.minimumZoomScale = kMinimumZoomScale / newZoomScale;
    self.maximumZoomScale = kMaximumZoomScale / newZoomScale;

    // Tell the contentView about its new scale. My contentView.zoomScale setter method
    // calls setNeedsDisplay, but you could also call it here
    contentView.zoomScale = newZoomScale;

    // My ContentView class overrides sizeThatFits to give its expected size with
    // zoomScale taken into account
    CGRect newContentSize = [contentView sizeThatFits];

    // update the content view's frame and the scroll view's contentSize with the new size
    contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height);
    self.contentSize = newContentSize;

    // Figure out the new contentOffset so that the contentView doesn't appear to move
    CGPoint newContentOffset = CGPointMake(contentCenter.x - size.width / newZoomScale / 2,
                                           contentCenter.y - size.height / newZoomScale / 2);
    newContentOffset.x = MIN(newContentOffset.x, newContentSize.width - size.width);
    newContentOffset.x = MAX(0, newContentOffset.x);
    newContentOffset.y = MIN(newContentOffset.y, newContentSize.height - .size.height);
    newContentOffset.y = MAX(0, newContentOffset.y);
    [self setContentOffset:newContentOffset animated:NO];
}
0 голосов
/ 10 июня 2014

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

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale{
    NSLog(@"finished zooming");

    NSLog(@"position x :%f",pin1.frame.origin.x);
    NSLog(@"position y :%f",pin1.frame.origin.y);


    CGRect frame = pin1.frame;
    frame.origin.x = pin1.frame.origin.x * scale;
    frame.origin.y = pin1.frame.origin.y * scale;
    pin1.frame = frame;

    NSLog(@"position x new :%f",pin1.frame.origin.x);
    NSLog(@"position y new:%f",pin1.frame.origin.y);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...