Skip to content

Commit 97c67ff

Browse files
author
Erik Ramalho
authored
Merge pull request #181 from AndySSSSSS/master
add downloading gif
2 parents c7c866c + f59b593 commit 97c67ff

File tree

5 files changed

+345
-2
lines changed

5 files changed

+345
-2
lines changed

plugin.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
<header-file src="src/ios/SOSPicker.h" />
3737
<source-file src="src/ios/SOSPicker.m" />
3838

39+
<header-file src="src/ios/GMImagePicker/FeHourGlass.h" />
40+
<source-file src="src/ios/GMImagePicker/FeHourGlass.m" />
41+
3942
<header-file src="src/ios/GMImagePicker/UIImage+fixOrientation.h" />
4043
<source-file src="src/ios/GMImagePicker/UIImage+fixOrientation.m" />
4144

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// FeCandyLoader.h
3+
// FeSpinner
4+
//
5+
// Created by Nghia Tran on 8/14/14.
6+
// Copyright (c) 2014 fe. All rights reserved.
7+
//
8+
9+
#import <UIKit/UIKit.h>
10+
11+
@interface FeHourGlass : UIView
12+
13+
// is running
14+
@property (assign, readonly, nonatomic) BOOL isShowing;
15+
16+
-(instancetype) initWithView:(UIView *) view;
17+
18+
-(void) show;
19+
20+
-(void) showWhileExecutingBlock:(dispatch_block_t) block;
21+
22+
-(void) showWhileExecutingBlock:(dispatch_block_t)block completion:(dispatch_block_t) completion;
23+
24+
-(void) showWhileExecutingSelector:(SEL) selector onTarget:(id) target withObject:(id) object;
25+
26+
-(void) showWhileExecutingSelector:(SEL)selector onTarget:(id)target withObject:(id)object completion:(dispatch_block_t) completion;
27+
28+
-(void) dismiss;
29+
30+
@end
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
//
2+
// FeCandyLoader.m
3+
// FeSpinner
4+
//
5+
// Created by Nghia Tran on 8/14/14.
6+
// Copyright (c) 2014 fe. All rights reserved.
7+
//
8+
9+
#import "FeHourGlass.h"
10+
#import <QuartzCore/QuartzCore.h>
11+
12+
#define kFe_HourGlass_Length 30.0f
13+
#define kFe_HourGlass_Duration 3.5f
14+
15+
@interface FeHourGlass ()
16+
{
17+
CGFloat width;
18+
CGFloat height;
19+
20+
// Target, method, object and block
21+
id targetForExecuting;
22+
SEL methodForExecuting;
23+
id objectForExecuting;
24+
dispatch_block_t completionBlock;
25+
}
26+
// Top
27+
@property (strong, nonatomic) CAShapeLayer *topLayer;
28+
29+
// Bottom
30+
@property (strong, nonatomic) CAShapeLayer *bottomLayer;
31+
32+
// Dash line
33+
@property (strong, nonatomic) CAShapeLayer *lineLayer;
34+
35+
// container Layer
36+
@property (strong, nonatomic) CALayer *containerLayer;
37+
38+
// Container view
39+
@property (weak, nonatomic) UIView *containerView;
40+
41+
// Animaiton
42+
@property (strong, nonatomic) CAKeyframeAnimation *topAnimation;
43+
44+
@property (strong, nonatomic) CAKeyframeAnimation *bottomAnimation;
45+
46+
@property (strong, nonatomic) CAKeyframeAnimation *lineAnimation;
47+
48+
@property(strong, nonatomic) CAKeyframeAnimation *containerAnimation;
49+
50+
///////////
51+
// Init
52+
-(void) initCommon;
53+
-(void) initContainer;
54+
-(void) initTop;
55+
-(void) initBottom;
56+
-(void) initLine;
57+
-(void) initAnimation;
58+
@end
59+
60+
@implementation FeHourGlass
61+
62+
-(instancetype) initWithView:(UIView *)view
63+
{
64+
self = [super init];
65+
if (self)
66+
{
67+
_containerView = view;
68+
69+
[self initCommon];
70+
71+
[self initContainer];
72+
73+
[self initTop];
74+
75+
[self initBottom];
76+
77+
[self initLine];
78+
79+
[self initAnimation];
80+
}
81+
return self;
82+
}
83+
-(void) initCommon
84+
{
85+
_isShowing = NO;
86+
87+
self.frame = CGRectMake(0, 0, _containerView.bounds.size.width, _containerView.bounds.size.height);
88+
self.backgroundColor = [UIColor clearColor];
89+
90+
width = sqrtf(kFe_HourGlass_Length * kFe_HourGlass_Length + kFe_HourGlass_Length * kFe_HourGlass_Length);
91+
height = sqrtf((kFe_HourGlass_Length * kFe_HourGlass_Length) - ((width / 2.0f) * (width / 2.0f)));
92+
}
93+
-(void) initContainer
94+
{
95+
_containerLayer = [CALayer layer];
96+
_containerLayer.backgroundColor = [UIColor clearColor].CGColor;
97+
_containerLayer.frame = CGRectMake(0, 0, width, height * 2);
98+
_containerLayer.anchorPoint = CGPointMake(0.5f, 0.5f);
99+
_containerLayer.position = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
100+
101+
[self.layer addSublayer:_containerLayer];
102+
}
103+
-(void) initTop
104+
{
105+
// BezierPath
106+
UIBezierPath *path = [UIBezierPath bezierPath];
107+
[path moveToPoint:CGPointMake(0, 0)];
108+
[path addLineToPoint:CGPointMake(width, 0)];
109+
[path addLineToPoint:CGPointMake(width / 2.0f, height)];
110+
[path addLineToPoint:CGPointMake(0, 0)];
111+
112+
[path closePath];
113+
114+
// Top Layer
115+
_topLayer = [CAShapeLayer layer];
116+
_topLayer.frame = CGRectMake(0, 0, width, height);
117+
_topLayer.path = path.CGPath;
118+
_topLayer.fillColor = [UIColor whiteColor].CGColor;
119+
_topLayer.strokeColor = [UIColor whiteColor].CGColor;
120+
_topLayer.lineWidth = 0.0f;
121+
_topLayer.anchorPoint = CGPointMake(0.5f, 1);
122+
_topLayer.position = CGPointMake(width / 2.0f, height);
123+
124+
[_containerLayer addSublayer:_topLayer];
125+
}
126+
-(void) initBottom
127+
{
128+
// BezierPath
129+
UIBezierPath *path = [UIBezierPath bezierPath];
130+
[path moveToPoint:CGPointMake(width / 2, 0)];
131+
[path addLineToPoint:CGPointMake(width, height)];
132+
[path addLineToPoint:CGPointMake(0, height )];
133+
[path addLineToPoint:CGPointMake(width / 2, 0)];
134+
135+
[path closePath];
136+
137+
// Top Layer
138+
_bottomLayer = [CAShapeLayer layer];
139+
_bottomLayer.frame = CGRectMake(0, height, width, height);
140+
_bottomLayer.path = path.CGPath;
141+
_bottomLayer.fillColor = [UIColor whiteColor].CGColor;
142+
_bottomLayer.strokeColor = [UIColor whiteColor].CGColor;
143+
_bottomLayer.lineWidth = 0.0f;
144+
_bottomLayer.anchorPoint = CGPointMake(0.5f, 1.0f);
145+
_bottomLayer.position = CGPointMake(width / 2.0f, height * 2.0f);
146+
_bottomLayer.transform = CATransform3DMakeScale(0, 0, 0);
147+
148+
[_containerLayer addSublayer:_bottomLayer];
149+
}
150+
-(void) initLine
151+
{
152+
// BezierPath
153+
UIBezierPath *path = [UIBezierPath bezierPath];
154+
[path moveToPoint:CGPointMake(width / 2, 0)];
155+
[path addLineToPoint:CGPointMake(width / 2, height)];
156+
157+
// Line Layer
158+
_lineLayer = [CAShapeLayer layer];
159+
_lineLayer.frame = CGRectMake(0, height, width, height);
160+
_lineLayer.strokeColor = [UIColor whiteColor].CGColor;
161+
_lineLayer.lineWidth = 1.0;
162+
_lineLayer.lineJoin = kCALineJoinMiter;
163+
_lineLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:1], nil];
164+
_lineLayer.lineDashPhase = 3.0f;
165+
_lineLayer.path = path.CGPath;
166+
_lineLayer.strokeEnd = 0.0f;
167+
168+
[_containerLayer addSublayer:_lineLayer];
169+
}
170+
-(void) initAnimation
171+
{
172+
if (YES) // Top Animation
173+
{
174+
_topAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
175+
_topAnimation.duration = kFe_HourGlass_Duration;
176+
_topAnimation.repeatCount = HUGE_VAL;
177+
_topAnimation.keyTimes = @[@0.0f, @0.9f, @1.0f];
178+
_topAnimation.values = @[@1.0f, @0.0f, @0.0f];
179+
}
180+
if (YES) // Bottom Animation
181+
{
182+
_bottomAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
183+
_bottomAnimation.duration = kFe_HourGlass_Duration;
184+
_bottomAnimation.repeatCount = HUGE_VAL;
185+
_bottomAnimation.keyTimes = @[@0.1f, @0.9f, @1.0f];
186+
_bottomAnimation.values = @[@0.0f, @1.0f, @1.0f];
187+
}
188+
if (YES) // Bottom Animation
189+
{
190+
_lineAnimation = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
191+
_lineAnimation.duration = kFe_HourGlass_Duration;
192+
_lineAnimation.repeatCount = HUGE_VAL;
193+
_lineAnimation.keyTimes = @[@0.0f, @0.1f, @0.9f, @1.0f];
194+
_lineAnimation.values = @[@0.0f, @1.0f, @1.0f, @1.0f];
195+
}
196+
if (YES) // Container Animation
197+
{
198+
_containerAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
199+
_containerAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.2f :1 :0.8f :0.0f];
200+
_containerAnimation.duration = kFe_HourGlass_Duration;
201+
_containerAnimation.repeatCount = HUGE_VAL;
202+
_containerAnimation.keyTimes = @[@0.8f, @1.0f];
203+
_containerAnimation.values = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:M_PI]];
204+
//_containerAnimation.calculationMode = kCAAnimationCubic;
205+
}
206+
}
207+
#pragma mark - Action
208+
-(void) show
209+
{
210+
if (_isShowing)
211+
return;
212+
213+
_isShowing = YES;
214+
215+
[_topLayer addAnimation:_topAnimation forKey:@"TopAnimatin"];
216+
[_bottomLayer addAnimation:_bottomAnimation forKey:@"BottomAnimation"];
217+
[_lineLayer addAnimation:_lineAnimation forKey:@"LineAnimation"];
218+
[_containerLayer addAnimation:_containerAnimation forKey:@"ContainerAnimation"];
219+
}
220+
-(void) dismiss
221+
{
222+
if (!_isShowing)
223+
return;
224+
225+
_isShowing = NO;
226+
227+
}
228+
-(void) showWhileExecutingBlock:(dispatch_block_t)block
229+
{
230+
[self showWhileExecutingBlock:block completion:nil];
231+
}
232+
-(void) showWhileExecutingSelector:(SEL)selector onTarget:(id)target withObject:(id)object
233+
{
234+
[self showWhileExecutingSelector:selector onTarget:target withObject:object completion:nil];
235+
236+
}
237+
-(void) showWhileExecutingBlock:(dispatch_block_t)block completion:(dispatch_block_t)completion
238+
{
239+
// Check block != nil
240+
if (block != nil)
241+
{
242+
[self show];
243+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^
244+
{
245+
block();
246+
247+
// Update UI
248+
dispatch_async(dispatch_get_main_queue(), ^{
249+
completion();
250+
[self dismiss];
251+
});
252+
});
253+
}
254+
}
255+
-(void) showWhileExecutingSelector:(SEL)selector onTarget:(id)target withObject:(id)object completion:(dispatch_block_t)completion
256+
{
257+
// Check Selector is responded
258+
if ([target respondsToSelector:selector])
259+
{
260+
methodForExecuting = selector;
261+
targetForExecuting = target;
262+
objectForExecuting = object;
263+
completionBlock = completion;
264+
265+
[self show];
266+
[NSThread detachNewThreadSelector:@selector(executingMethod) toTarget:self withObject:nil];
267+
}
268+
}
269+
#pragma mark Helper method
270+
-(void) executingMethod
271+
{
272+
@autoreleasepool {
273+
#pragma clang diagnostic push
274+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
275+
// Start executing the requested task
276+
[targetForExecuting performSelector:methodForExecuting withObject:objectForExecuting];
277+
#pragma clang diagnostic pop
278+
// Task completed, update view in main thread (note: view operations should
279+
// be done only in the main thread)
280+
dispatch_async(dispatch_get_main_queue(), ^{
281+
completionBlock();
282+
[self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];
283+
});
284+
285+
}
286+
}
287+
-(void) cleanUp
288+
{
289+
NSLog(@"Clean up");
290+
if (objectForExecuting)
291+
objectForExecuting = nil;
292+
if (methodForExecuting)
293+
methodForExecuting = nil;
294+
if (targetForExecuting)
295+
targetForExecuting = nil;
296+
if (completionBlock)
297+
completionBlock = nil;
298+
[self dismiss];
299+
}
300+
301+
@end

src/ios/GMImagePicker/GMGridViewCell.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
//#import "MRCircularProgressView.h"
1010
#import <Photos/Photos.h>
11+
#import "FeHourGlass.h"
1112

1213

1314
@interface GMGridViewCell : UICollectionViewCell
@@ -29,6 +30,8 @@
2930
- (void)bind:(PHAsset *)asset;
3031

3132
//@property (nonatomic, strong) MRCircularProgressView *circularProgressView;
33+
34+
@property (strong, nonatomic) FeHourGlass *hourGlass;
3235
-(void)show_progress;
3336
-(void)set_progress:(float)value animated:(BOOL)animated;
3437
-(void)hide_progress;
@@ -37,4 +40,4 @@
3740
-(void)show_fetching;
3841
-(void)hide_fetching;
3942

40-
@end
43+
@end

src/ios/GMImagePicker/GMGridViewCell.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @interface GMGridViewCell ()
1616

1717

1818
@implementation GMGridViewCell
19-
2019
//@synthesize circularProgressView;
2120

2221
static UIFont *titleFont;
@@ -27,6 +26,7 @@ @implementation GMGridViewCell
2726
static UIColor *selectedColor;
2827
static UIColor *disabledColor;
2928

29+
3030
+ (void)initialize
3131
{
3232
titleFont = [UIFont systemFontOfSize:12];
@@ -150,10 +150,16 @@ - (id)initWithFrame:(CGRect)frame
150150

151151
-(void)show_progress{
152152
// [self.circularProgressView setHidden:false];
153+
self.hourGlass = [[FeHourGlass alloc] initWithView:self];
154+
[self addSubview:self.hourGlass];
155+
[self.hourGlass show];
153156
}
154157

155158
-(void)hide_progress{
156159
// [self.circularProgressView setHidden:true];
160+
// [self.hourGlass dismiss];
161+
[self.hourGlass removeFromSuperview];
162+
157163
}
158164

159165
-(void)set_progress:(float)value animated:(BOOL)animated{

0 commit comments

Comments
 (0)