Objective c 淡入/淡出UIScrollView';s的内容,就像Mobile Safari在其选项卡中所做的一样

Objective c 淡入/淡出UIScrollView';s的内容,就像Mobile Safari在其选项卡中所做的一样,objective-c,iphone,cocoa-touch,uiscrollview,core-animation,Objective C,Iphone,Cocoa Touch,Uiscrollview,Core Animation,注意:我在下面的更新答案中添加了我的新解决方案。 我试图重现我们在iPhone/iPod touch上的Mobile Safari标签中看到的效果 基本上,它是一个UIScrollView,包含4个可重用的UIView(就像环形缓冲区一样),并水平滚动。滚动时,UIView的不透明度将随偏移量无缝淡入/淡出 目前,我在-(void)scrollViewDidScroll:(UIScrollView*)scrollView中完成所有脏工作。例如从UIScrollView获取contentOffse

注意:我在下面的更新答案中添加了我的新解决方案。

我试图重现我们在iPhone/iPod touch上的Mobile Safari标签中看到的效果

基本上,它是一个UIScrollView,包含4个可重用的UIView(就像环形缓冲区一样),并水平滚动。滚动时,UIView的不透明度将随偏移量无缝淡入/淡出

目前,我在
-(void)scrollViewDidScroll:(UIScrollView*)scrollView
中完成所有脏工作。例如从UIScrollView获取contentOffset,确定分页操作,计算contentOffset和每个UIView位置之间的增量,并在调用
scrollViewDidScroll:
时确定/设置每个UIView的alpha值

它工作正常,性能还可以,一切都很顺利,但唯一的问题是计算量太大


我尝试了UIView的
beginAnimations:
commitAnimations:
,但是在
scrollViewDidScroll:
中没有用,因为1)新的alpha值仍然必须由我自己计算,2)scrollViewDidScroll:在滚动时一直被调用,在这里做动画没有意义。有没有办法用核心动画重写这个部分?因此,我不必自己计算每个UIView的alpha值,相反,我可以将整个工作留给核心动画。

正如您从调用scrollViewDidScroll:的频率中所注意到的,UIScrollView不会简单地触发并忘记核心动画转换:它会根据触摸、加速度手动移动边界,等等。没有直接的方法来改变这一点

但是,如果您被滚动事件淹没,您可以尝试以下技巧:

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

    // do the rest of your work here
}
-(无效)scrollViewDidScroll:(UIScrollView*)scrollView
{
NSTimeInterval时间戳=[[NSDate date]TimeIntervalnce1970];
如果(时间戳-_savedTimestamp)<0.1)
返回;
_savedTimestamp=时间戳;
//你剩下的工作都在这里做
}

H

更新

我想出了另一种方法来更新每个页面的alpha值。创建内容视图时,我使用KVO将Observer添加到UIScrollView的contentOffset中:

[self.scrollView addObserver:[self.contentViews objectAtIndex:i] 
                  forKeyPath:@"contentOffset" 
                     options:NSKeyValueObservingOptionNew
                     context:@selector(updateAlpha:)];
这样,当contentOffset更改时,我的每个ContentView都会收到消息:

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {
    [self performSelector:(SEL)context withObject:change];
}
我的ContentView可以在滚动时自行进行计算和设置动画:

- (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];
}
-(void)updateAlpha:(NSDictionary*)更改{
CGFloat offset=[[change objectForKey:NSKeyValueChangeNewKey]CGPointValue].x;
CGFloat原点=[self frame].origin.x;
CGFloat delta=fabs(原点-偏移);
[UIView beginAnimations:@“衰退”上下文:无];
如果(增量<[自帧].size.width){
self.alpha=1-delta/self.frame.size.width*0.7;
}否则{
self.alpha=0.3;
}
[UIView委员会];
}
当然,从superview中删除内容视图时需要删除观察者,并在创建新内容视图时再次添加观察者


希望这对那些想做同样事情的人有所帮助。

哈芬奇,谢谢你的想法。虽然它不是完美的,但仍然可以节省一些cpu资源。现在就找到这个,它太棒了-谢谢分享!一个小问题:初始alpha没有为屏幕外的单独视图设置。我想我可以显式地调用updateAlpha:explicit,但也许在一开始就显式地设置contentOffset就足够了。思想?