Merge pull request #3 from material-foundation/develop
Merged with latest MDC changes and bumped version to 3.0.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fdb87d..cb7b46d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 3.0.0
+
+##### Breaking
+
+* Pulled in latest changes from [MDC](https://github.com/material-components/material-components-ios/commits/develop/components/SpritedAnimationView)
+up to and including [sha 2d654](https://github.com/material-components/material-components-ios/commit/2d654)
+
## 2.0.0
##### Breaking
diff --git a/MDFSpritedAnimationView.podspec b/MDFSpritedAnimationView.podspec
index 4ce24f7..0e00b0a 100644
--- a/MDFSpritedAnimationView.podspec
+++ b/MDFSpritedAnimationView.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "MDFSpritedAnimationView"
- s.version = "2.0.0"
+ s.version = "3.0.0"
s.authors = { 'Chris Cox' => 'cjcox@google.com' }
s.summary = "A control providing an alternative to animating an array of images with an UIImageView."
s.homepage = "https://github.com/material-foundation/MDFSpritedAnimationView"
diff --git a/README.md b/README.md
index be940d0..266d093 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,18 @@
# MDFSpritedAnimationView
[![Build Status](https://travis-ci.org/google/MDFSpritedAnimationView.svg?branch=master)](https://travis-ci.org/google/MDFSpritedAnimationView)
+![SpritedAnimationView](docs/assets/sprited_animation_view.png)
+<!--{: .ios-screenshot .right }-->
+
This control provides an alternative to animating an array of images with an `UIImageView`. Only a
single image composed of individual sprite frames is used, and animation simply consists of
updating the layer `contentsRect`.
+<!--{: .intro }-->
-## Installation
+## Requirements
-### Requirements
-
-- Xcode 7.0 or higher.
-- iOS SDK version 7.0 or higher.
-
-### Installation with CocoaPods
-
-To add this component to your Xcode project using CocoaPods, add the following to your `Podfile`:
-
-~~~ bash
-pod 'MDFScrollViewDelegateMultiplexer'
-~~~
-
-Then, run the following command:
-
-~~~ bash
-$ pod install
-~~~
-
-- - -
+- Xcode 7.0 or higher
+- iOS SDK version 7.0 or higher
## Create a sprite sheet asset
@@ -58,13 +44,13 @@
| List Sprite Sheet | Grid Sprite Sheet |
| :---------------------------: | :---------------------------: |
-| ![List Icon](examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid.png) | ![Grid Icon](examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list.png) |
+| ![List Icon](examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid.png) | ![Grid Icon](examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list.png) |
#### Two-state example
```objectivec
// Animate the sprited view.
-[_animationView startAnimatingWithCompletion:^{
+[_animationView startAnimatingWithCompletion:^(BOOL finished) {
// When animation completes, toggle image.
_toggle = !_toggle;
@@ -76,10 +62,27 @@
## Usage
+### Importing
+
+Before using Sprited Animation View, you'll need to import it:
+
+<!--<div class="material-code-render" markdown="1">-->
+#### Objective-C
+
+~~~ objc
+#import "MaterialSpritedAnimationView.h"
+~~~
+
+#### Swift
+~~~ swift
+import MaterialComponents
+~~~
+<!--</div>-->
+
Integrating the `spritedAnimationView` is somewhat similar to adding an `UIImageView` to a view.
```objectivec
-#import "MDFSpritedAnimationView.h"
+#import "MaterialSpritedAnimationView.h"
// Create a Sprited Animation View.
UIImage *spriteSheet = [UIImage imageNamed:@"myImage"];
@@ -89,7 +92,7 @@
[self.view addSubview:animationView];
// To Animate.
-[animationView startAnimatingWithCompletion:^{
+[animationView startAnimatingWithCompletion:^(BOOL finished) {
NSLog(@"Done animating.");
}];
```
diff --git a/docs/assets/sprited_animation_view.png b/docs/assets/sprited_animation_view.png
new file mode 100644
index 0000000..ab30e55
--- /dev/null
+++ b/docs/assets/sprited_animation_view.png
Binary files differ
diff --git a/examples/SpritedAnimationViewTypicalUseViewController.m b/examples/SpritedAnimationViewTypicalUseViewController.m
index b37e574..a683386 100644
--- a/examples/SpritedAnimationViewTypicalUseViewController.m
+++ b/examples/SpritedAnimationViewTypicalUseViewController.m
@@ -14,25 +14,30 @@
limitations under the License.
*/
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
#import "SpritedAnimationViewTypicalUseViewController.h"
-#import "MDFSpritedAnimationView.h"
+#import "MaterialSpritedAnimationView.h"
-static NSString *const kSpriteList = @"gos_sprite_list__grid";
-static NSString *const kSpriteGrid = @"gos_sprite_grid__list";
+static NSString *const kSpriteList = @"sprite_list__grid";
+static NSString *const kSpriteGrid = @"sprite_grid__list";
@implementation SpritedAnimationViewTypicalUseViewController {
MDFSpritedAnimationView *_animationView;
BOOL _toggle;
}
-+ (NSArray *)catalogHierarchy {
- // Support for catalog by convention.
- return @[ @"Sprited Animation View", @"Typical use" ];
+// TODO: Support other categorizational methods.
++ (NSArray *)catalogBreadcrumbs {
+ return @[ @"Sprited Animation View", @"Sprited Animation View" ];
+}
+
++ (NSString *)catalogDescription {
+ return @"This control provides an alternative to animating an array of images with an"
+ " UIImageView.";
+}
+
++ (BOOL)catalogIsPrimaryDemo {
+ return YES;
}
- (void)viewDidLoad {
@@ -41,26 +46,103 @@
self.view.backgroundColor = [UIColor whiteColor];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
- UIImage *spriteImage = [UIImage imageNamed:kSpriteList
- inBundle:bundle
- compatibleWithTraitCollection:nil];
+ UIImage *spriteImage =
+ [UIImage imageNamed:kSpriteList inBundle:bundle compatibleWithTraitCollection:nil];
_animationView = [[MDFSpritedAnimationView alloc] initWithSpriteSheetImage:spriteImage];
_animationView.frame = CGRectMake(0, 0, 30, 30);
_animationView.center = self.view.center;
- _animationView.tintColor = [UIColor blueColor];
+ _animationView.translatesAutoresizingMaskIntoConstraints = NO;
+ UIColor *blueColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+ _animationView.tintColor = blueColor;
[self.view addSubview:_animationView];
+ // AnimationView Layout Constraints
+ NSLayoutConstraint *animationViewWidthConstraint =
+ [NSLayoutConstraint constraintWithItem:_animationView
+ attribute:NSLayoutAttributeWidth
+ relatedBy:NSLayoutRelationEqual
+ toItem:nil
+ attribute:NSLayoutAttributeNotAnAttribute
+ multiplier:1.0
+ constant:30];
+ animationViewWidthConstraint.active = true;
+ NSLayoutConstraint *animationViewHeightConstraint =
+ [NSLayoutConstraint constraintWithItem:_animationView
+ attribute:NSLayoutAttributeHeight
+ relatedBy:NSLayoutRelationEqual
+ toItem:nil
+ attribute:NSLayoutAttributeNotAnAttribute
+ multiplier:1.0
+ constant:30];
+ animationViewHeightConstraint.active = true;
+ NSLayoutConstraint *animationViewXConstraint =
+ [NSLayoutConstraint constraintWithItem:self.view
+ attribute:NSLayoutAttributeCenterX
+ relatedBy:NSLayoutRelationEqual
+ toItem:_animationView
+ attribute:NSLayoutAttributeCenterX
+ multiplier:1.0
+ constant:0.0];
+ animationViewXConstraint.active = true;
+ NSLayoutConstraint *animationViewYConstraint =
+ [NSLayoutConstraint constraintWithItem:self.view
+ attribute:NSLayoutAttributeCenterY
+ relatedBy:NSLayoutRelationEqual
+ toItem:_animationView
+ attribute:NSLayoutAttributeCenterY
+ multiplier:1.0
+ constant:0.0];
+ animationViewYConstraint.active = true;
+
// Add label with tap instructions.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectOffset(self.view.bounds, 0, 30)];
+ label.translatesAutoresizingMaskIntoConstraints = NO;
label.text = @"Tap anywhere to animate icon.";
label.textColor = [UIColor colorWithWhite:0 alpha:0.8];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
+ // Label Layout Constraints
+ NSLayoutConstraint *labelWidthConstraint =
+ [NSLayoutConstraint constraintWithItem:label
+ attribute:NSLayoutAttributeWidth
+ relatedBy:NSLayoutRelationEqual
+ toItem:self.view
+ attribute:NSLayoutAttributeWidth
+ multiplier:1.0
+ constant:0.0];
+ labelWidthConstraint.active = true;
+ NSLayoutConstraint *labelHeightConstraint =
+ [NSLayoutConstraint constraintWithItem:label
+ attribute:NSLayoutAttributeHeight
+ relatedBy:NSLayoutRelationEqual
+ toItem:self.view
+ attribute:NSLayoutAttributeHeight
+ multiplier:1.0
+ constant:0.0];
+ labelHeightConstraint.active = true;
+ NSLayoutConstraint *labelXConstraint =
+ [NSLayoutConstraint constraintWithItem:label
+ attribute:NSLayoutAttributeCenterX
+ relatedBy:NSLayoutRelationEqual
+ toItem:self.view
+ attribute:NSLayoutAttributeCenterX
+ multiplier:1.0
+ constant:0.0];
+ labelXConstraint.active = true;
+ NSLayoutConstraint *labelYConstraint =
+ [NSLayoutConstraint constraintWithItem:label
+ attribute:NSLayoutAttributeCenterY
+ relatedBy:NSLayoutRelationEqual
+ toItem:self.view
+ attribute:NSLayoutAttributeCenterY
+ multiplier:1.0
+ constant:30.0];
+ labelYConstraint.active = true;
+
// Add tap gesture to view.
UITapGestureRecognizer *tapGesture =
- [[UITapGestureRecognizer alloc] initWithTarget:self
- action:@selector(didTap:)];
+ [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
[self.view addGestureRecognizer:tapGesture];
}
@@ -68,7 +150,7 @@
recognizer.enabled = NO;
// Animate the sprited view.
- [_animationView startAnimatingWithCompletion:^{
+ [_animationView startAnimatingWithCompletion:^(BOOL finished) {
// When animation completes, toggle image.
_toggle = !_toggle;
diff --git a/examples/app/Podfile.lock b/examples/app/Podfile.lock
index 0daec6f..bdac9e5 100644
--- a/examples/app/Podfile.lock
+++ b/examples/app/Podfile.lock
@@ -1,5 +1,5 @@
PODS:
- - MDFSpritedAnimationView (2.0.0)
+ - MDFSpritedAnimationView (3.0.0)
DEPENDENCIES:
- MDFSpritedAnimationView (from `../../`)
@@ -9,7 +9,7 @@
:path: "../../"
SPEC CHECKSUMS:
- MDFSpritedAnimationView: 91e3a415e50ec36ea19c0fcb46905eaaff2f16fc
+ MDFSpritedAnimationView: 75dead8462287f526818520af1e377226c3bb671
PODFILE CHECKSUM: 80195f268febc54d39de014ff5b21653bbb11547
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/Contents.json b/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/Contents.json
deleted file mode 100644
index e2a76ca..0000000
--- a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images": [
- {
- "filename": "gos_sprite_grid__list.png",
- "idiom": "universal",
- "scale": "1x"
- },
- {
- "filename": "gos_sprite_grid__list_2x.png",
- "idiom": "universal",
- "scale": "2x"
- },
- {
- "filename": "gos_sprite_grid__list_3x.png",
- "idiom": "universal",
- "scale": "3x"
- }
- ],
- "info": {
- "author": "xcode",
- "version": 1
- }
-}
\ No newline at end of file
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/Contents.json b/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/Contents.json
deleted file mode 100644
index 66faadd..0000000
--- a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images": [
- {
- "filename": "gos_sprite_list__grid.png",
- "idiom": "universal",
- "scale": "1x"
- },
- {
- "filename": "gos_sprite_list__grid_2x.png",
- "idiom": "universal",
- "scale": "2x"
- },
- {
- "filename": "gos_sprite_list__grid_3x.png",
- "idiom": "universal",
- "scale": "3x"
- }
- ],
- "info": {
- "author": "xcode",
- "version": 1
- }
-}
\ No newline at end of file
diff --git a/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/Contents.json b/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/Contents.json
new file mode 100644
index 0000000..eb09a34
--- /dev/null
+++ b/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_grid__list.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_grid__list@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_grid__list@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list.png b/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list.png
Binary files differ
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list_2x.png b/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list@2x.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list_2x.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list@2x.png
Binary files differ
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list_3x.png b/examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list@3x.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_grid__list.imageset/gos_sprite_grid__list_3x.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_grid__list.imageset/sprite_grid__list@3x.png
Binary files differ
diff --git a/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/Contents.json b/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/Contents.json
new file mode 100644
index 0000000..9580d40
--- /dev/null
+++ b/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_list__grid.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_list__grid@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "sprite_list__grid@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid.png b/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid.png
Binary files differ
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid_2x.png b/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid@2x.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid_2x.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid@2x.png
Binary files differ
diff --git a/examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid_3x.png b/examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid@3x.png
similarity index 100%
rename from examples/resources/SpritedAnimationView.xcassets/gos_sprite_list__grid.imageset/gos_sprite_list__grid_3x.png
rename to examples/resources/SpritedAnimationView.xcassets/sprite_list__grid.imageset/sprite_list__grid@3x.png
Binary files differ
diff --git a/src/MDFSpritedAnimationView.h b/src/MDFSpritedAnimationView.h
index ae73047..a368ed9 100644
--- a/src/MDFSpritedAnimationView.h
+++ b/src/MDFSpritedAnimationView.h
@@ -69,8 +69,19 @@
@param spriteSheetImage A vertical sprite sheet of square images.
@return Initialized sprited animation view.
*/
-- (nonnull instancetype)initWithSpriteSheetImage:
- (nullable UIImage *)spriteSheetImage NS_DESIGNATED_INITIALIZER;
+- (nonnull instancetype)initWithSpriteSheetImage:(nullable UIImage *)spriteSheetImage
+ NS_DESIGNATED_INITIALIZER;
+
+/**
+ Creates an animated sprite view. Use this initializer if your images are non-square.
+
+ @param spriteSheetImage A vertical sprite sheet of images.
+ @param numberOfFrames The number of frames in the sprite sheet image. Used for calculating
+ the size of each frame.
+ @return Initialized sprited animation view.
+ */
+- (nonnull instancetype)initWithSpriteSheetImage:(nullable UIImage *)spriteSheetImage
+ numberOfFrames:(NSInteger)numberOfFrames;
/** Please use initWithSpriteSheetImage:. */
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
@@ -82,7 +93,7 @@
@param completion Block called when transition completes.
*/
-- (void)startAnimatingWithCompletion:(nullable void (^)())completion;
+- (void)startAnimatingWithCompletion:(nullable void (^)(BOOL finished))completion;
/** Stop the animation. */
- (void)stop;
diff --git a/src/MDFSpritedAnimationView.m b/src/MDFSpritedAnimationView.m
index 02c4d8e..42f5414 100644
--- a/src/MDFSpritedAnimationView.m
+++ b/src/MDFSpritedAnimationView.m
@@ -14,14 +14,20 @@
limitations under the License.
*/
-#import "MDFSpritedAnimationView.h"
+#import "MaterialSpritedAnimationView.h"
#import <QuartzCore/QuartzCore.h>
static NSString *const kSpriteAnimationKey = @"spriteAnimate";
static const NSInteger kSpriteFrameRateDefault = 60;
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDFSpritedAnimationView () <CAAnimationDelegate>
+@end
+#endif
+
@interface MDFSpritedAnimationView ()
+@property(nonatomic, copy) void (^pendingCompletionBlock)(BOOL finished);
@property(nonatomic, assign) NSInteger numberOfFrames;
@property(nonatomic, assign) CGFloat singleFrameWidthInPercent; // 1 / numberOfFrames
@property(nonatomic, strong) CALayer *spriteLayer;
@@ -61,6 +67,24 @@
return self;
}
+- (instancetype)initWithSpriteSheetImage:(UIImage *)spriteSheetImage
+ numberOfFrames:(NSInteger)numberOfFrames {
+ MDFSpritedAnimationView *animationView = [self initWithSpriteSheetImage:spriteSheetImage];
+ animationView.numberOfFrames = numberOfFrames;
+ animationView.singleFrameWidthInPercent = 1.0f / numberOfFrames;
+ [animationView updateSpriteAnimationLayer];
+
+ return animationView;
+}
+
+- (CGSize)intrinsicContentSize {
+ if (_spriteSheetImage) {
+ CGFloat width = _spriteSheetImage.size.width;
+ return CGSizeMake(width, width);
+ }
+ return [super intrinsicContentSize];
+}
+
- (void)layoutSubviews {
[super layoutSubviews];
@@ -69,12 +93,13 @@
self.spriteLayer.bounds = self.bounds;
}
-- (void)startAnimatingWithCompletion:(void (^)())completion {
- [CATransaction begin];
- [CATransaction setCompletionBlock:completion];
+- (void)startAnimatingWithCompletion:(void (^)(BOOL finished))completion {
+ [self stop];
- NSMutableArray *linearValues = [NSMutableArray array];
- NSMutableArray *keyTimes = [NSMutableArray array];
+ self.pendingCompletionBlock = completion;
+
+ NSMutableArray<NSValue *> *linearValues = [NSMutableArray array];
+ NSMutableArray<NSNumber *> *keyTimes = [NSMutableArray array];
for (NSInteger i = 0; i < _numberOfFrames; i++) {
CGRect contentsRect =
CGRectMake(0, i * _singleFrameWidthInPercent, 1, _singleFrameWidthInPercent);
@@ -83,6 +108,7 @@
}
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
+ animation.delegate = self;
animation.duration = (NSTimeInterval)_numberOfFrames / (NSTimeInterval)_frameRate;
animation.values = linearValues;
animation.keyTimes = keyTimes;
@@ -95,22 +121,37 @@
}
[self.spriteLayer addAnimation:animation forKey:kSpriteAnimationKey];
- [CATransaction commit];
}
- (void)stop {
- // Removing the animation will cause the completion block to be also called.
+ // Removing the animation will trigger |animationDidStop| and therefore the completion block, but
+ // there is no guarantee it happens atomically so to ensure predictable call-order we manually
+ // trigger the completion block here.
+ void (^block)(BOOL cancelled) = self.pendingCompletionBlock;
+ self.pendingCompletionBlock = nil;
+
+ if (block) {
+ block(NO);
+ }
[self.spriteLayer removeAnimationForKey:kSpriteAnimationKey];
}
- (void)seekToBeginning {
+ [self stop];
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
self.spriteLayer.contentsRect = CGRectMake(0, 0, 1, _singleFrameWidthInPercent);
+ [CATransaction commit];
[self.spriteLayer setNeedsDisplay];
}
- (void)seekToEnd {
+ [self stop];
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
self.spriteLayer.contentsRect =
CGRectMake(0, 1.0f - _singleFrameWidthInPercent, 1, _singleFrameWidthInPercent);
+ [CATransaction commit];
[self.layer setNeedsDisplay];
}
@@ -158,13 +199,31 @@
CGSize spriteSheetSize = [_spriteSheetImage size];
CGFloat singleFrameWidth = spriteSheetSize.width;
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+ // Disable implicit animations for these assignments
CALayer *layer = self.spriteLayer;
layer.contents = (id)_spriteSheetImage.CGImage;
layer.bounds = CGRectMake(0, 0, singleFrameWidth, singleFrameWidth);
layer.contentsRect = CGRectMake(0, 0, 1, _singleFrameWidthInPercent);
+ [CATransaction commit];
}
-#pragma mark Setters
+#pragma mark - CAAnimationDelegate
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)finished {
+ if (anim != [self.spriteLayer animationForKey:kSpriteAnimationKey]) {
+ return;
+ }
+ void (^block)(BOOL cancelled) = self.pendingCompletionBlock;
+ self.pendingCompletionBlock = nil;
+
+ if (block) {
+ block(finished);
+ }
+}
+
+#pragma mark - Setters
- (void)setTintColor:(UIColor *)tintColor {
if (_tintColor == tintColor) {
@@ -178,6 +237,7 @@
}
- (void)setSpriteSheetImage:(UIImage *)spriteSheetImage {
+ [self stop];
if (!spriteSheetImage) {
_spriteSheetImage = spriteSheetImage;
return;
@@ -188,9 +248,8 @@
_numberOfFrames = (NSInteger)floor(spriteSheetSize.height / singleFrameWidth);
_singleFrameWidthInPercent = 1.0f / _numberOfFrames;
_spriteSheetImage = [self colorizedSpriteSheet:spriteSheetImage];
-
+ [self invalidateIntrinsicContentSize];
[self updateSpriteAnimationLayer];
- [self.spriteLayer removeAllAnimations];
}
@end
diff --git a/src/MaterialSpritedAnimationView.h b/src/MaterialSpritedAnimationView.h
new file mode 100644
index 0000000..5df1f1c
--- /dev/null
+++ b/src/MaterialSpritedAnimationView.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFSpritedAnimationView.h"
diff --git a/tests/unit/MDFSpritedAnimationViewTests.m b/tests/unit/MDFSpritedAnimationViewTests.m
index 65960e3..37b6628 100644
--- a/tests/unit/MDFSpritedAnimationViewTests.m
+++ b/tests/unit/MDFSpritedAnimationViewTests.m
@@ -16,9 +16,9 @@
#import <XCTest/XCTest.h>
-#import "MDFSpritedAnimationView.h"
+#import "MaterialSpritedAnimationView.h"
-static NSString *const kSpriteList = @"gos_sprite_list__grid";
+static NSString *const kSpriteList = @"mdc_sprite_list__grid";
static NSString *const kExpectationDescription = @"animatingWithCompletion";
@interface SpritedAnimationViewTests : XCTestCase
@@ -45,7 +45,7 @@
XCTestExpectation *expectation = [self expectationWithDescription:kExpectationDescription];
// Fulfill expectation after completion of animation.
- [animationView startAnimatingWithCompletion:^{
+ [animationView startAnimatingWithCompletion:^(BOOL completion) {
[expectation fulfill];
}];
@@ -71,8 +71,8 @@
XCTestExpectation *expectation = [self expectationWithDescription:kExpectationDescription];
// Fulfill expectation after completion of animation.
- [animationView startAnimatingWithCompletion:^{
- [expectation fulfill];
+ [animationView startAnimatingWithCompletion:^(BOOL finished) {
+ [expectation fulfill];
}];
[self waitForExpectationsWithTimeout:1.0