2009-05-17 66 views
13

注意:我在下面的UPDATE答案中添加了我的新解决方案。淡入/淡出UIScrollView的内容如Mobile Safari在其标签

我尝试重新创建我们在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)新的阿尔法值还是要由我自己来计算,和2)scrollViewDidScroll:滚动时不停叫,这是毫无意义的,在这里做动画。有什么方法可以用Core Animation重写这部分?所以我不必对每个UIView的alpha值进行数学运算,相反,我可以将整个作品留给Core Animation。

回答

26

UPDATE

我想出了另一种方式更新每个页面的alpha值。当创建内容来看,我用韩国国际志愿者组织与UIScrollView的contentOffset到的addObserver:

[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]; 
} 

当然,您需要在从超级视图中删除内容视图时删除观察者,并在创建新内容视图时再次添加它们。

希望帮助那些想要做同样的事情的人。

+1

现在就找到它,它很棒 - 谢谢你的分享!一个小故障:最初的alpha并没有设置为唯一的离屏视图。我想我可以明确地调用updateAlpha,但也许在开始时显式设置contentOffset就足够了。思考? – 2011-03-06 03:56:20

2

正如您已经注意到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

+0

hatfinch,感谢您的想法。虽然它不完美,但仍然可以节省一些CPU的能力。 – digdog 2009-05-21 13:56:54