Mobile Safari がタブで行うのと同じように、UIScrollView のコンテンツをフェードイン/フェードアウトします
-
22-08-2019 - |
質問
注記:以下の更新回答に新しいソリューションを追加しました。
iPhone/iPod touch の Mobile Safari タブで見られた効果を再現してみます。
基本的に、これは 4 つの再利用可能な UIView (リング バッファーのように動作) を保持し、水平方向にスクロールする UIScrollView です。スクロールすると、UIView の不透明度がオフセットでシームレスにフェードイン/フェードアウトします。
現在、私はすべての汚れ仕事を行っています - (void)scrollViewDidScroll:(UIScrollView *)scrollView
. 。UIScrollView から contentOffset を取得し、ページングを決定し、contentOffset と各 UIView の位置の差分を計算し、その時点での各 UIView のアルファ値を決定/設定します。 scrollViewDidScroll:
と呼ばれていました。
動作し、パフォーマンスも問題なく、すべてがスムーズに動作します。しかし、唯一の問題は計算が多すぎることです。
UIViewを試してみた beginAnimations:
そして commitAnimations:
, 、しかし、それは役に立たない scrollViewDidScroll:
, 1) 新しいアルファ値はまだ自分で計算する必要があり、2)scrollViewDidScroll があるためです。スクロール時に呼び出され続けるため、ここでアニメーションを実行しても意味がありません。この部分をCoreAnimationで書き直す方法はあるでしょうか?そのため、各 UIView のアルファ値を自分で計算する必要はなく、作業全体を Core Animation に任せることができます。
解決
アップデート
各ページのアルファ値を更新する別の方法を思いつきました。コンテンツ ビューを作成するときは、KVO を使用して UIScrollView の contentOffset で addObserver を使用します。
[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];
}
もちろん、スーパービューからコンテンツ ビューを削除するときにオブザーバーを削除し、新しいコンテンツ ビューを作成するときにオブザーバーを再度追加する必要があります。
同じことをしたい人にとって、これが役立つことを願っています。
他のヒント
あなたはどのくらいの頻度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