魅せるuiの作り方 | ios 7エンジニア勉強会
DESCRIPTION
TRANSCRIPT
魅せるUIの作り方iOS 7 エンジニア勉強会@ヤフー
2013/10/7カカオジャパン 佐藤新悟
iOS 7 らしい UI
•フラットデザイン、それだけ?•物理法則にもとづいたリアルなアニメーション
•視差を利用した奥行きの表現•磨りガラスのような透過表現
UIKit Dynamics
• UIKitのための2次元物理エンジン•これまでのアニメーションの仕組みを置き換えるものではない
•ゲームのためのものではない(Sprite Kitを使おう)
Demo
Gravity and Collision
UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[square1,square2]];
UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[square1,square2]];collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[animator addBehavior:gravityBeahvior];[animator addBehavior:collisionBehavior];
ArchitectureUIDynamicAnimator
UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior
View View View
Reference View
Architecture
Subview Subview Subview
Superview
UIDynamicBehavior• UIGravityBehavior• UICollisionBehavior• UIAttachmentBehavior• UISnapBehavior• UIPushBehavior• UIDynamicItemBehavior
Demo
UIGravityBehavior
UIGravityBehavior* gravityBeahavior = [[UIGravityBehavior alloc] initWithItems:@[self.square1]];
gravityBeahavior.gravityDirection = CGVectorMake(0.0f, 1.0f);
gravityBeahavior.magnitude = 1.0f;gravityBeahavior.angle = -M_PI/2.0;
•重力の強さと方向を設定可能
UICollisionBehaviorUICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems: @[self.square1, self.square2]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;// UICollisionBehaviorModeBoundaries, UICollisionBehaviorModeItems
CGPoint p0; CGPoint p1;[collisionBehavior addBoundaryWithIdentifier:@"b0" fromPoint:p0 toPoint:p1];
UIBezierPath *path;[collisionBehavior addBoundaryWithIdentifier:@"b1" forPath:path];
• view同士の衝突も可能• CGPointで直線を指定、またはUIBezierPathを使って境界を追加可能
UIAttachmentBehaviorCGPoint anchorPoint = CGPointMake(self.square1.center.x, self.square1.center.y - 100.0);UIOffset offset = UIOffsetMake(-25.0, -25.0);UIAttachmentBehavior* attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.square1 offsetFromCenter:offset attachedToAnchor:anchorPoint];
attachmentBehavior.frequency = 1.0;attachmentBehavior.damping = 0.1;
• view上の点と指定した点を繋ぐ• バネのように伸び縮みさせることもできる
UISnapBehavior
UISnapBehavior* snapBehavior = [[UISnapBehavior alloc] initWithItem:self.square1 snapToPoint:point];
• viewを指定した点に吸い付くようにする
UIPushBehaviortypedef NS_ENUM(NSInteger, UIPushBehaviorMode) { UIPushBehaviorModeContinuous, UIPushBehaviorModeInstantaneous}
UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.square1] mode:UIPushBehaviorModeInstantaneous];pushBehavior.angle = 0.0;pushBehavior.magnitude = 1.0;
• 瞬間的に力を加える instantaneous と、継続的に力を加える continuous のモードがある
• 力の方向と強さを設定可能
UIDynamicItemBehaviorUIDynamicItemBehavior* propertiesBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.square1]];propertiesBehavior.elasticity = 0.5;
• 指定したviewの特性を変える• elasticity: 弾性• friction: 摩擦• density: 密度(質量)• resistance: 抵抗• angularResistance: 回転に対する抵抗• allowsRotation: itemの回転を許すか否か
Motion Effects
•端末の傾きに応じて視差効果を与える
Motion Effects
UIMotionEffectUIInterpolatingMotionEffect *xAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];xAxis.minimumRelativeValue = @(-20.0f);xAxis.maximumRelativeValue = @20.0f; UIInterpolatingMotionEffect *yAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];yAxis.minimumRelativeValue = @(-20.0f);yAxis.maximumRelativeValue = @20.0f; UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];group.motionEffects = @[xAxis, yAxis];[self.button addMotionEffect:group];
Blur Effect
Blur Effect• UIKit標準のコントロールは背景をぼかして透過する処理を自動で行う
• APIは公開されていないので独自のviewで同じことをやるには自力で実装が必要
• WWDCのサンプルコードとしてUIImageのカテゴリが配布されている (UIImage+ImageEffects)
• 静止画を作るだけなので動的なコンテンツへの利用は難しい
• 静止画だけでも工夫次第でできることは多い
Demo
Blur Effect// viewのスナップショットを撮るUIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO];UIImage *bgImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();
// blurをかけるbgImage = [bgImage applyLightEffect];
• -[CALayer renderInContext:] よりも高速
(A) 背景view
(B) 降りてくるviewclipsToBounds = YES
(C) blurred imageBのsubview
B の動きに合わせてC のframeを調整して動かないように見せる
まとめ• 物理法則にもとづいたリアルなアニメーション→ UIKit Dynamics
• 視差を利用した奥行きの表現→ Motion Effects
• 磨りガラスのような透過表現• UIKit標準コントロールを利用• 自前実装はパフォーマンスに注意
参考資料• UIKit Dynamics Catalog
https://developer.apple.com/library/ios/samplecode/DynamicsCatalog
• WWDC 2013 sessionshttps://developer.apple.com/wwdc/videos/
• Getting Started with UIKit Dynamics• Advanced Techniques with UIKit Dynamics• Implementing Engaging UI on iOS(Motion Effects, Snapshot, Blur)
• WWDC 2013 Sample Codeshttps://developer.apple.com/wwdc/resources/
• iOS_RunningWithASnap• iOS_UIImageEffects (ぼかし用UIImageカテゴリ)