iAd Gallery風 Roll UI
iAd GalleryというアプリがUS App Storeにあって、Tab -> BrowseがこういうUIになってます。

このUIの利点はなんだろう、iAdだからリッチ感を出したくて普通のTableViewからひとひねりした、って感じでしょうか。あと、表示するのがバナーなので、TableViewで出すんじゃなくて、何か物体感を出したかったのかな、と思う。
僕の実装は、UIScrollViewを無限スクロール可能にして、その上で見えている部分を半円として、各Cellの位置を計算しているだけ。
円上の位置が決まると、sin,cosで中心からの高さと距離が分かるので、それでview.transformをセットして大きさを変える
という感じ。
通常はRunLoopの終わりで勝手に呼ばれる。
なので呼ぶ必要は無いんだけど、何かの事情でRunLoopがその後終了しないとき
呼んであげると、アニメーションが始まる。
たとえば、こんなコードで試せる。
[CATransaction flush]を呼ばないとアニメーションしない。
- (void)action
{
CABasicAnimation* animation;
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:1.0];
animation.toValue = [NSNumber numberWithFloat:0.0];
animation.duration = 2.0;
[_layer addAnimation:animation forKey:nil];
//Call flush self!
[CATransaction flush];
while (1) {
//block current Run Loop
}
}
あくまで、Current Run Loopなので外から とかやってもダメ。[self performSelector:@selector(flush) withObject:nil afterDelay:1.0];
- (void)flush
{
[CATransaction flush];
}
but does it float - Definition: God is the shortest distance between zero and infinity
nsx:
ssbt:
CAReplicatorLayerはSubLayerを.instance***にしたがってinstanceCount個copyして表示するLayer。
instance**は全部アニメーション可能なので、CAAnimationと組み合わせるととんでもないことになる。
以下、普通に複数表示すだけのコード。
.instanceTransformに画像のwidth右に動かすTransformを渡しているので、contentLayerが横に5個(4個コピーされて)表示される。
CALayer* contentLayer = [CALayer layer];
UIImage* image = [UIImage imageNamed:@"CA.jpg"];
CGRect rect;
rect.origin = CGPointZero;
rect.size = image.size;
contentLayer.frame = rect;
contentLayer.contents = (id)image.CGImage;
CAReplicatorLayer* replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = rect;
replicatorLayer.instanceCount = 5;
[replicatorLayer addSublayer:contentLayer];
[self.view.layer addSublayer:replicatorLayer];
CATransform3D transform;
transform = CATransform3DMakeTranslation(rect.size.width,
0,
0);
replicatorLayer.instanceTransform = transform;
.colorsはアニメーション可能なので
こんなのができる。
…
[self performSelector:@selector(hoge:) withObject:gradientLayer afterDelay:1.0];
}
- (void)hoge:(CAGradientLayer*)gradientLayer
{
[CATransaction begin];
[CATransaction setAnimationDuration:2.0];
NSMutableArray* array = [NSMutableArray array];
[array addObject:(id)[UIColor blueColor].CGColor];
[array addObject:(id)[UIColor redColor].CGColor];
gradientLayer.colors = array;
[CATransaction commit];
}
CAGradientLayerのHello world!
- (void)viewDidLoad
{
CAGradientLayer* gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.view.bounds;
gradientLayer.startPoint = CGPointZero;
gradientLayer.endPoint = CGPointMake(1.0, 1.0);
NSMutableArray* array = [NSMutableArray array];
[array addObject:(id)[UIColor redColor].CGColor];
[array addObject:(id)[UIColor blueColor].CGColor];
gradientLayer.colors = array;
[self.view.layer addSublayer:gradientLayer];
}
OS Xのみしか無いCARenderer、iOSでもUndocument Classだけど存在してて
OpenGLの世界と繋げるClassなので、EAGLContextを使うようになってる。
+ (id)rendererWithEAGLContext:(id)fp8 options:(id)fp12;
OS Xのイニシャライズメソッドはこれ
+ (CARenderer *)rendererWithCGLContext:(void *)ctx options:(NSDictionary *)dict;
UIViewのPropertyのいくつかはアニメーション可能
Animatable UIView properties
に書いてある
だがしかし、それだけではなくて
UIScrollViewのcontentOffsetも
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
があるように、アニメーションできる。
ということは、ドキュメントには書いてないけど
UIScrollViewのcontentOffsetはAnimatable Propertyである。
ので、
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:10];
[scrollView setContentOffset:CGPointMake(0, 500)];
[UIView commitAnimations];
とやると、10秒でスクロールする。
たぶん、animatedという引数があるやつは全部この方法でアニメーション時間や、Timing Function(アニメーションのカーブ)が変更できる。
どうも違うみたい。要継続調査
(この調査がなんの役に立つというのだろう)
CAScrollLayerは、上に乗っけてるSubLayerをスクロールさせるLayer。
CAScrollLayer.contentsがスクロールするわけではない!
UIScrollViewみたいにバウンドするアニメーションを提供してくれるわけではないので、ちょいと使いづらいかなぁ。逆に言えばCAKeyframeAnimationを使って、設定してあげれば自分でバウンドが作れる。
と思ったけど
- (void)scrollToPoint:(CGPoint)p;
しかないので、それたぶん無理。
Core Animationはかなり謎が多いことが予想されるけど、CABasicAnimationの + (id)defaultValueForKey:(NSString *)key
のkeyに見たことが無いのが来るのが判明して、上書きしたら面白いことになった。
keyがframeIntervalのとき、[NSNumber numberWithFloat:1.0/10]って返すと、フレームレートが10になる。フェードだとカクカクフェードアウトする
影を付けるとこうなる。
影を使う場合、光がどこか差しているのか、を考えないと不自然になる。
拡大したときは、カードが上に上がるのだがら影も変わるのだ