Внедрить / вывести содержимое UIScrollView, как это делает Mobile Safari на своей вкладке - PullRequest
13 голосов
/ 17 мая 2009

ПРИМЕЧАНИЕ: я добавил свое новое решение в ответе ОБНОВЛЕНИЯ ниже.

Я пытаюсь воссоздать эффекты, которые мы видели на вкладке Mobile Safari на iPhone / iPod touch.

По сути, это UIScrollView, который содержит 4 многократно используемых UIView (действует как кольцевой буфер) и прокручивает по горизонтали. При прокрутке, непрозрачность UIView будет плавно исчезать со смещением.

В настоящее время я делаю всю грязную работу в - (void)scrollViewDidScroll:(UIScrollView *)scrollView. Например, получение contentOffset из UIScrollView, определение постраничного представления, вычисление разницы между contentOffset и каждым положением UIView и определение / установка значения альфа каждого UIView в момент вызова scrollViewDidScroll:.

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

Я пробовал UIView beginAnimations: и commitAnimations:, но в scrollViewDidScroll: это бесполезно, поскольку 1) новое альфа-значение все еще нужно вычислять самостоятельно, и 2) scrollViewDidScroll: вызывается при прокрутке, бессмысленно сделать анимацию здесь. Есть ли способ переписать эту часть с Core Animation? Так что мне не нужно делать математику самостоятельно по альфа-значению каждого UIView, вместо этого я могу оставить все работы в Core Animation.

Ответы [ 2 ]

26 голосов
/ 24 мая 2009

UPDATE

Я придумал другой способ обновить альфа-значение каждой страницы. При создании представления содержимого я использую KVO для добавленияObserver с contentOffset UIScrollView:

[self.scrollView addObserver:[self.contentViews objectAtIndex:i] 
                  forKeyPath:@"contentOffset" 
                     options:NSKeyValueObservingOptionNew
                     context:@selector(updateAlpha:)];

Чтобы каждый из моих contentViews получал сообщение при изменении contentOffset:

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {
    [self performSelector:(SEL)context withObject:change];
}

А мои contentViews могут самостоятельно выполнять вычисления и анимировать их при прокрутке:

- (void)updateAlpha:(NSDictionary *)change {
    CGFloat offset = [[change objectForKey:NSKeyValueChangeNewKey] CGPointValue].x;
    CGFloat origin = [self frame].origin.x;
    CGFloat delta = fabs(origin - offset);

    [UIView beginAnimations:@"Fading" context:nil];
    if (delta < [self frame].size.width) {
        self.alpha = 1 - delta/self.frame.size.width*0.7;
    } else {
        self.alpha = 0.3;
    }
    [UIView commitAnimations];
}

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

Надеюсь, что это поможет тем, кто хочет сделать то же самое.

2 голосов
/ 18 мая 2009

Как вы заметили из того, как часто вызывается scrollViewDidScroll:, UIScrollView не просто запускает и забывает переход Core Animation: он вручную перемещает границы в соответствии с касаниями, ускорением и т. Д. Нет простого способа изменить это .

Однако, если вас завалили событиями прокрутки, вы можете попробовать трюк, подобный следующему:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];
    if (timestamp - _savedTimestamp) < 0.1)
        return;
    _savedTimestamp = timestamp;

    // do the rest of your work here
}

H

...