forked from organicmaps/organicmaps
[new downloader][ios] Updated circular progress.
This commit is contained in:
parent
9dacca71c0
commit
372c6b7811
11 changed files with 72 additions and 87 deletions
|
@ -4,6 +4,7 @@ typedef NS_ENUM(NSInteger, MWMCircularProgressState)
|
|||
MWMCircularProgressStateNormal,
|
||||
MWMCircularProgressStateSelected,
|
||||
MWMCircularProgressStateProgress,
|
||||
MWMCircularProgressStateSpinner,
|
||||
MWMCircularProgressStateFailed,
|
||||
MWMCircularProgressStateCompleted
|
||||
};
|
||||
|
@ -24,11 +25,9 @@ typedef NS_ENUM(NSInteger, MWMCircularProgressState)
|
|||
|
||||
- (void)setImage:(nonnull UIImage *)image forState:(MWMCircularProgressState)state;
|
||||
- (void)setColor:(nonnull UIColor *)color forState:(MWMCircularProgressState)state;
|
||||
- (void)setInvertColor:(BOOL)invertColor;
|
||||
|
||||
- (nonnull instancetype)init __attribute__((unavailable("init is not available")));
|
||||
- (nonnull instancetype)initWithParentView:(nonnull UIView *)parentView;
|
||||
- (void)reset;
|
||||
- (void)startSpinner:(BOOL)isInvert;
|
||||
- (void)stopSpinner;
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,18 +16,24 @@
|
|||
if (self)
|
||||
{
|
||||
[[NSBundle mainBundle] loadNibNamed:self.class.className owner:self options:nil];
|
||||
[parentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
[parentView addSubview:self.rootView];
|
||||
[self reset];
|
||||
self.state = MWMCircularProgressStateNormal;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.rootView removeFromSuperview];
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
{
|
||||
_progress = 0.;
|
||||
[self.rootView updatePath:0.];
|
||||
self.nextProgressToAnimate = nil;
|
||||
self.state = MWMCircularProgressStateNormal;
|
||||
}
|
||||
|
||||
- (void)setImage:(nonnull UIImage *)image forState:(MWMCircularProgressState)state
|
||||
|
@ -40,17 +46,9 @@
|
|||
[self.rootView setColor:color forState:state];
|
||||
}
|
||||
|
||||
#pragma mark - Spinner
|
||||
|
||||
- (void)startSpinner:(BOOL)isInvert
|
||||
- (void)setInvertColor:(BOOL)invertColor
|
||||
{
|
||||
[self reset];
|
||||
[self.rootView startSpinner:isInvert];
|
||||
}
|
||||
|
||||
- (void)stopSpinner
|
||||
{
|
||||
[self.rootView stopSpinner];
|
||||
self.rootView.isInvertColor = invertColor;
|
||||
}
|
||||
|
||||
#pragma mark - Animation
|
||||
|
@ -77,9 +75,10 @@
|
|||
{
|
||||
if (progress <= _progress)
|
||||
{
|
||||
[self reset];
|
||||
self.state = MWMCircularProgressStateSpinner;
|
||||
return;
|
||||
}
|
||||
self.rootView.state = MWMCircularProgressStateProgress;
|
||||
if (self.rootView.animating)
|
||||
{
|
||||
if (progress > self.nextProgressToAnimate.floatValue)
|
||||
|
@ -87,14 +86,21 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
[self.rootView animateFromValue:_progress toValue:progress];
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self.rootView animateFromValue:self->_progress toValue:progress];
|
||||
});
|
||||
_progress = progress;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setState:(MWMCircularProgressState)state
|
||||
{
|
||||
self.rootView.state = state;
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self reset];
|
||||
self.rootView.state = state;
|
||||
});
|
||||
}
|
||||
|
||||
- (MWMCircularProgressState)state
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
@property (nonatomic, readonly) BOOL animating;
|
||||
|
||||
@property (nonatomic) MWMCircularProgressState state;
|
||||
@property (nonatomic) BOOL isInvertColor;
|
||||
|
||||
- (nonnull instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("initWithFrame is not available")));
|
||||
- (nonnull instancetype)init __attribute__((unavailable("init is not available")));
|
||||
|
@ -13,7 +14,5 @@
|
|||
- (void)animateFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue;
|
||||
|
||||
- (void)updatePath:(CGFloat)progress;
|
||||
- (void)startSpinner:(BOOL)isInvert;
|
||||
- (void)stopSpinner;
|
||||
|
||||
@end
|
||||
|
|
|
@ -56,6 +56,7 @@ static inline CGFloat angleWithProgress(CGFloat progress)
|
|||
[self setColor:clearColor forState:MWMCircularProgressStateNormal];
|
||||
[self setColor:clearColor forState:MWMCircularProgressStateSelected];
|
||||
[self setColor:progressColor forState:MWMCircularProgressStateProgress];
|
||||
[self setColor:progressColor forState:MWMCircularProgressStateSpinner];
|
||||
[self setColor:clearColor forState:MWMCircularProgressStateFailed];
|
||||
[self setColor:clearColor forState:MWMCircularProgressStateCompleted];
|
||||
}
|
||||
|
@ -97,30 +98,20 @@ static inline CGFloat angleWithProgress(CGFloat progress)
|
|||
self.progressLayer.strokeColor = self.progressLayerColor;
|
||||
CGRect rect = CGRectInset(self.bounds, kLineWidth, kLineWidth);
|
||||
self.backgroundLayer.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath;
|
||||
UIImage * normalImage = nil;
|
||||
switch (self.state)
|
||||
{
|
||||
case MWMCircularProgressStateNormal:
|
||||
normalImage = self.images[@(MWMCircularProgressStateNormal)];
|
||||
self.button.coloring = MWMButtonColoringBlack;
|
||||
break;
|
||||
case MWMCircularProgressStateSelected:
|
||||
normalImage = self.images[@(MWMCircularProgressStateSelected)];
|
||||
self.button.coloring = MWMButtonColoringBlue;
|
||||
break;
|
||||
case MWMCircularProgressStateProgress:
|
||||
normalImage = self.images[@(MWMCircularProgressStateProgress)];
|
||||
self.button.coloring = MWMButtonColoringBlue;
|
||||
break;
|
||||
case MWMCircularProgressStateSpinner:
|
||||
case MWMCircularProgressStateFailed:
|
||||
normalImage = self.images[@(MWMCircularProgressStateFailed)];
|
||||
self.button.coloring = MWMButtonColoringBlue;
|
||||
break;
|
||||
case MWMCircularProgressStateCompleted:
|
||||
normalImage = self.images[@(MWMCircularProgressStateCompleted)];
|
||||
self.button.coloring = MWMButtonColoringBlue;
|
||||
break;
|
||||
}
|
||||
UIImage * normalImage = self.images[@(self.state)];
|
||||
[self.button setImage:normalImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
|
@ -144,23 +135,20 @@ static inline CGFloat angleWithProgress(CGFloat progress)
|
|||
|
||||
#pragma mark - Spinner
|
||||
|
||||
- (void)startSpinner:(BOOL)isInvert
|
||||
- (void)startSpinner
|
||||
{
|
||||
if (!self.spinner.hidden)
|
||||
return;
|
||||
self.spinner.hidden = NO;
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
self.backgroundLayer.hidden = self.progressLayer.hidden = YES;
|
||||
NSUInteger const animationImagesCount = 12;
|
||||
NSMutableArray * animationImages = [NSMutableArray arrayWithCapacity:animationImagesCount];
|
||||
NSString * postfix = ([UIColor isNightMode] && !isInvert) || (![UIColor isNightMode] && isInvert) ? @"dark" : @"light";
|
||||
for (NSUInteger i = 0; i < animationImagesCount; ++i)
|
||||
animationImages[i] = [UIImage imageNamed:[NSString stringWithFormat:@"Spinner_%@_%@", @(i+1), postfix]];
|
||||
self.backgroundLayer.hidden = self.progressLayer.hidden = YES;
|
||||
NSUInteger const animationImagesCount = 12;
|
||||
NSMutableArray * animationImages = [NSMutableArray arrayWithCapacity:animationImagesCount];
|
||||
NSString * postfix = ([UIColor isNightMode] && !self.isInvertColor) || (![UIColor isNightMode] && self.isInvertColor) ? @"dark" : @"light";
|
||||
for (NSUInteger i = 0; i < animationImagesCount; ++i)
|
||||
animationImages[i] = [UIImage imageNamed:[NSString stringWithFormat:@"Spinner_%@_%@", @(i+1), postfix]];
|
||||
|
||||
self.spinner.animationImages = animationImages;
|
||||
[self.spinner startAnimating];
|
||||
});
|
||||
self.spinner.animationImages = animationImages;
|
||||
[self.spinner startAnimating];
|
||||
}
|
||||
|
||||
- (void)stopSpinner
|
||||
|
@ -168,29 +156,23 @@ static inline CGFloat angleWithProgress(CGFloat progress)
|
|||
if (self.spinner.hidden)
|
||||
return;
|
||||
self.spinner.hidden = YES;
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
self.backgroundLayer.hidden = self.progressLayer.hidden = NO;
|
||||
[self.spinner.layer removeAllAnimations];
|
||||
});
|
||||
self.backgroundLayer.hidden = self.progressLayer.hidden = NO;
|
||||
[self.spinner.layer removeAllAnimations];
|
||||
}
|
||||
|
||||
#pragma mark - Animation
|
||||
|
||||
- (void)animateFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self updatePath:toValue];
|
||||
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
|
||||
animation.duration = kDefaultAnimationDuration;
|
||||
animation.repeatCount = 1;
|
||||
animation.fromValue = @(fromValue / toValue);
|
||||
animation.toValue = @1;
|
||||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||
animation.delegate = self.owner;
|
||||
[self.progressLayer addAnimation:animation forKey:kAnimationKey];
|
||||
});
|
||||
[self updatePath:toValue];
|
||||
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
|
||||
animation.duration = kDefaultAnimationDuration;
|
||||
animation.repeatCount = 1;
|
||||
animation.fromValue = @(fromValue / toValue);
|
||||
animation.toValue = @1;
|
||||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||
animation.delegate = self.owner;
|
||||
[self.progressLayer addAnimation:animation forKey:kAnimationKey];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
@ -199,6 +181,10 @@ static inline CGFloat angleWithProgress(CGFloat progress)
|
|||
{
|
||||
if (_state == state)
|
||||
return;
|
||||
if (state == MWMCircularProgressStateSpinner)
|
||||
[self startSpinner];
|
||||
else if (_state == MWMCircularProgressStateSpinner)
|
||||
[self stopSpinner];
|
||||
_state = state;
|
||||
[self refreshProgress];
|
||||
}
|
||||
|
|
|
@ -40,20 +40,21 @@
|
|||
{
|
||||
[[NSBundle mainBundle] loadNibNamed:self.class.className owner:self options:nil];
|
||||
[parentView addSubview:self.rootView];
|
||||
self.progressView = [[MWMCircularProgress alloc] initWithParentView:self.progressViewWrapper];
|
||||
self.progressView.delegate = self;
|
||||
[self setupProgressImages];
|
||||
[self setupProgressView];
|
||||
self.delegate = delegate;
|
||||
[self showRequest];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupProgressImages
|
||||
- (void)setupProgressView
|
||||
{
|
||||
self.progressView = [[MWMCircularProgress alloc] initWithParentView:self.progressViewWrapper];
|
||||
self.progressView.delegate = self;
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_download"] forState:MWMCircularProgressStateNormal];
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_download"] forState:MWMCircularProgressStateSelected];
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_close_spinner"] forState:MWMCircularProgressStateProgress];
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_close_spinner"] forState:MWMCircularProgressStateSpinner];
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_download_error"] forState:MWMCircularProgressStateFailed];
|
||||
[self.progressView setImage:[UIImage imageNamed:@"ic_check"] forState:MWMCircularProgressStateCompleted];
|
||||
}
|
||||
|
@ -112,7 +113,6 @@
|
|||
- (void)setDownloadFailed
|
||||
{
|
||||
self.progressView.state = MWMCircularProgressStateFailed;
|
||||
[self.progressView stopSpinner];
|
||||
}
|
||||
|
||||
#pragma mark - MWMCircularProgressDelegate
|
||||
|
@ -125,7 +125,7 @@
|
|||
if (progress.state == MWMCircularProgressStateFailed)
|
||||
{
|
||||
s.RetryDownloadNode(m_countryId);
|
||||
[self.progressView startSpinner:NO];
|
||||
self.progressView.state = MWMCircularProgressStateSpinner;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -141,9 +141,8 @@
|
|||
[[Statistics instance] logEvent:kStatEventName(kStatDownloadRequest, kStatDownloadMap)];
|
||||
[MapsAppDelegate downloadNode:m_countryId alertController:self.delegate.alertController onSuccess:^
|
||||
{
|
||||
self.progressView.progress = 0.0;
|
||||
[self showRequest];
|
||||
[self.progressView startSpinner:NO];
|
||||
self.progressView.state = MWMCircularProgressStateSpinner;
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,8 @@ using namespace osm;
|
|||
{
|
||||
self.spinnerView.hidden = NO;
|
||||
self.spinner = [[MWMCircularProgress alloc] initWithParentView:self.spinnerView];
|
||||
[self.spinner startSpinner:YES];
|
||||
[self.spinner setInvertColor:YES];
|
||||
self.spinner.state = MWMCircularProgressStateSpinner;
|
||||
self.loginTextField.enabled = NO;
|
||||
self.passwordTextField.enabled = NO;
|
||||
self.forgotButton.enabled = NO;
|
||||
|
@ -109,8 +110,6 @@ using namespace osm;
|
|||
- (void)stopSpinner
|
||||
{
|
||||
self.spinnerView.hidden = YES;
|
||||
[self.spinnerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
[self.spinner stopSpinner];
|
||||
self.spinner = nil;
|
||||
self.loginTextField.enabled = YES;
|
||||
self.passwordTextField.enabled = YES;
|
||||
|
|
|
@ -116,15 +116,14 @@ NSString * getVerifier(NSString * urlString)
|
|||
{
|
||||
self.spinnerView.hidden = NO;
|
||||
self.spinner = [[MWMCircularProgress alloc] initWithParentView:self.spinnerView];
|
||||
[self.spinner startSpinner:YES];
|
||||
[self.spinner setInvertColor:YES];
|
||||
self.spinner.state = MWMCircularProgressStateSpinner;
|
||||
self.webView.userInteractionEnabled = NO;
|
||||
}
|
||||
|
||||
- (void)stopSpinner
|
||||
{
|
||||
self.spinnerView.hidden = YES;
|
||||
[self.spinnerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
[self.spinner stopSpinner];
|
||||
self.spinner = nil;
|
||||
self.webView.userInteractionEnabled = YES;
|
||||
}
|
||||
|
|
|
@ -163,7 +163,6 @@ extern NSString * const kTTSStatusWasChangedNotification;
|
|||
{
|
||||
[self.routePreview stateError];
|
||||
self.activeRouteTypeButton.state = MWMCircularProgressStateFailed;
|
||||
[self.activeRouteTypeButton stopSpinner];
|
||||
}
|
||||
|
||||
- (void)updateDashboard
|
||||
|
@ -248,7 +247,7 @@ extern NSString * const kTTSStatusWasChangedNotification;
|
|||
[[Statistics instance]
|
||||
logEvent:kStatPointToPoint
|
||||
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatPedestrian}];
|
||||
[self.routePreview.vehicleProgressView stopSpinner];
|
||||
self.routePreview.vehicleProgressView.state = MWMCircularProgressStateNormal;
|
||||
type = routing::RouterType::Pedestrian;
|
||||
}
|
||||
else
|
||||
|
@ -256,7 +255,7 @@ extern NSString * const kTTSStatusWasChangedNotification;
|
|||
[[Statistics instance]
|
||||
logEvent:kStatPointToPoint
|
||||
withParameters:@{kStatAction : kStatChangeRoutingMode, kStatValue : kStatVehicle}];
|
||||
[self.routePreview.pedestrianProgressView stopSpinner];
|
||||
self.routePreview.pedestrianProgressView.state = MWMCircularProgressStateNormal;
|
||||
type = routing::RouterType::Vehicle;
|
||||
}
|
||||
f.CloseRouting();
|
||||
|
@ -265,7 +264,7 @@ extern NSString * const kTTSStatusWasChangedNotification;
|
|||
[self.routePreview selectProgress:progress];
|
||||
if (!self.delegate.isPossibleToBuildRoute)
|
||||
return;
|
||||
[progress startSpinner:NO];
|
||||
progress.state = MWMCircularProgressStateSpinner;
|
||||
[self.delegate buildRoute];
|
||||
}
|
||||
|
||||
|
@ -336,7 +335,7 @@ extern NSString * const kTTSStatusWasChangedNotification;
|
|||
[self removePanel:self.nextTurnPanel];
|
||||
// [self removePanel:self.lanesPanel];
|
||||
[self setupActualRoute];
|
||||
[self.activeRouteTypeButton startSpinner:NO];
|
||||
self.activeRouteTypeButton.state = MWMCircularProgressStateSpinner;
|
||||
}
|
||||
|
||||
- (void)showStateReady
|
||||
|
|
|
@ -57,12 +57,14 @@ static CGFloat const kAdditionalHeight = 20.;
|
|||
[self.pedestrianProgressView setImage:[UIImage imageNamed:@"ic_walk"] forState:MWMCircularProgressStateFailed];
|
||||
[self.pedestrianProgressView setImage:[UIImage imageNamed:@"ic_walk"] forState:MWMCircularProgressStateSelected];
|
||||
[self.pedestrianProgressView setImage:[UIImage imageNamed:@"ic_walk"] forState:MWMCircularProgressStateProgress];
|
||||
[self.pedestrianProgressView setImage:[UIImage imageNamed:@"ic_walk"] forState:MWMCircularProgressStateSpinner];
|
||||
[self.pedestrianProgressView setImage:[UIImage imageNamed:@"ic_walk"] forState:MWMCircularProgressStateCompleted];
|
||||
self.vehicleProgressView = [[MWMCircularProgress alloc] initWithParentView:self.vehicle];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateNormal];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateFailed];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateSelected];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateProgress];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateSpinner];
|
||||
[self.vehicleProgressView setImage:[UIImage imageNamed:@"ic_drive"] forState:MWMCircularProgressStateCompleted];
|
||||
}
|
||||
|
||||
|
@ -99,8 +101,8 @@ static CGFloat const kAdditionalHeight = 20.;
|
|||
|
||||
- (void)statePrepare
|
||||
{
|
||||
[self.pedestrianProgressView stopSpinner];
|
||||
[self.vehicleProgressView stopSpinner];
|
||||
self.pedestrianProgressView.state = MWMCircularProgressStateNormal;
|
||||
self.vehicleProgressView.state = MWMCircularProgressStateNormal;
|
||||
self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI);
|
||||
self.goButton.hidden = NO;
|
||||
self.goButton.enabled = NO;
|
||||
|
@ -193,7 +195,6 @@ static CGFloat const kAdditionalHeight = 20.;
|
|||
- (void)deselectPedestrian
|
||||
{
|
||||
self.pedestrianProgressView.state = MWMCircularProgressStateNormal;
|
||||
[self.pedestrianProgressView stopSpinner];
|
||||
}
|
||||
|
||||
- (void)selectProgress:(MWMCircularProgress *)progress;
|
||||
|
@ -213,7 +214,6 @@ static CGFloat const kAdditionalHeight = 20.;
|
|||
- (void)deselectVehicle
|
||||
{
|
||||
self.vehicleProgressView.state = MWMCircularProgressStateNormal;
|
||||
[self.vehicleProgressView stopSpinner];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
|
|
|
@ -72,14 +72,13 @@
|
|||
{
|
||||
self.spinnerView.hidden = NO;
|
||||
self.spinner = [[MWMCircularProgress alloc] initWithParentView:self.spinnerView];
|
||||
[self.spinner startSpinner:YES];
|
||||
[self.spinner setInvertColor:YES];
|
||||
self.spinner.state = MWMCircularProgressStateSpinner;
|
||||
}
|
||||
|
||||
- (void)stopSpinner
|
||||
{
|
||||
self.spinnerView.hidden = YES;
|
||||
[self.spinnerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
[self.spinner stopSpinner];
|
||||
self.spinner = nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ using namespace storage;
|
|||
{
|
||||
self.downloadButton.hidden = YES;
|
||||
self.progressWrapper.hidden = NO;
|
||||
[self.progressView startSpinner:NO];
|
||||
self.progressView.state = MWMCircularProgressStateSpinner;
|
||||
}
|
||||
|
||||
#pragma mark - MWMFrameworkDrapeObserver
|
||||
|
|
Loading…
Add table
Reference in a new issue