From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001
From: 单军华
Date: Wed, 11 Jul 2018 10:47:42 +0800
Subject: [PATCH] 首次上传
---
screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m | 542 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 542 insertions(+), 0 deletions(-)
diff --git a/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m b/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m
new file mode 100755
index 0000000..ba0e7fd
--- /dev/null
+++ b/screendisplay/Pods/M13ProgressSuite/Classes/NavigationController/UINavigationController+M13ProgressViewBar.m
@@ -0,0 +1,542 @@
+//
+// UINavigationController+M13ProgressViewBar.m
+// M13ProgressView
+//
+
+#import "UINavigationController+M13ProgressViewBar.h"
+#import "UIApplication+M13ProgressSuite.h"
+#import <objc/runtime.h>
+
+//Keys to set properties since one cannot define properties in a category.
+static char oldTitleKey;
+static char displayLinkKey;
+static char animationFromKey;
+static char animationToKey;
+static char animationStartTimeKey;
+static char progressKey;
+static char progressViewKey;
+static char indeterminateKey;
+static char indeterminateLayerKey;
+static char isShowingProgressKey;
+static char primaryColorKey;
+static char secondaryColorKey;
+static char backgroundColorKey;
+static char backgroundViewKey;
+
+@implementation UINavigationController (M13ProgressViewBar)
+
+#pragma mark Title
+
+- (void)setProgressTitle:(NSString *)title
+{
+ //Change the title on screen.
+ NSString *oldTitle = [self getOldTitle];
+ if (oldTitle == nil) {
+ //We haven't changed the navigation bar yet. So store the original before changing it.
+ [self setOldTitle:self.visibleViewController.navigationItem.title];
+ }
+
+ if (title != nil) {
+ self.visibleViewController.navigationItem.title = title;
+ } else {
+ self.visibleViewController.navigationItem.title = oldTitle;
+ [self setOldTitle:nil];
+ }
+}
+
+#pragma mark Progress
+
+- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
+{
+ CADisplayLink *displayLink = [self getDisplayLink];
+ if (animated == NO) {
+ if (displayLink) {
+ //Kill running animations
+ [displayLink invalidate];
+ [self setDisplayLink:nil];
+ }
+ [self setProgress:progress];
+ } else {
+ [self setAnimationStartTime:CACurrentMediaTime()];
+ [self setAnimationFromValue:[self getProgress]];
+ [self setAnimationToValue:progress];
+ if (!displayLink) {
+ //Create and setup the display link
+ [displayLink invalidate];
+ displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateProgress:)];
+ [self setDisplayLink:displayLink];
+ [displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
+ } /*else {
+ //Reuse the current display link
+ }*/
+ }
+}
+
+- (void)animateProgress:(CADisplayLink *)displayLink
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ CGFloat dt = (displayLink.timestamp - [self getAnimationStartTime]) / [self getAnimationDuration];
+ if (dt >= 1.0) {
+ //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
+ [displayLink invalidate];
+ [self setDisplayLink:nil];
+ [self setProgress:[self getAnimationToValue]];
+ return;
+ }
+
+ //Set progress
+ [self setProgress:[self getAnimationFromValue] + dt * ([self getAnimationToValue] - [self getAnimationFromValue])];
+
+ });
+}
+
+- (void)finishProgress
+{
+ UIView *progressView = [self getProgressView];
+ UIView *backgroundView = [self getBackgroundView];
+ if (progressView && backgroundView) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [UIView animateWithDuration:0.1 animations:^{
+ CGRect progressFrame = progressView.frame;
+ progressFrame.size.width = self.navigationBar.frame.size.width;
+ progressView.frame = progressFrame;
+ } completion:^(BOOL finished) {
+ [UIView animateWithDuration:0.5 animations:^{
+ progressView.alpha = 0;
+ backgroundView.alpha = 0;
+ } completion:^(BOOL finished) {
+ [progressView removeFromSuperview];
+ [backgroundView removeFromSuperview];
+ backgroundView.alpha = 1;
+ progressView.alpha = 1;
+ [self setTitle:nil];
+ [self setIsShowingProgressBar:NO];
+ }];
+ }];
+ });
+ }
+}
+
+- (void)cancelProgress
+{
+ UIView *progressView = [self getProgressView];
+ UIView *backgroundView = [self getBackgroundView];
+
+ if (progressView && backgroundView) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [UIView animateWithDuration:0.5 animations:^{
+ progressView.alpha = 0;
+ backgroundView.alpha = 0;
+ } completion:^(BOOL finished) {
+ [progressView removeFromSuperview];
+ [backgroundView removeFromSuperview];
+ progressView.alpha = 1;
+ backgroundView.alpha = 1;
+ [self setTitle:nil];
+ [self setIsShowingProgressBar:NO];
+ }];
+ });
+ }
+}
+
+#pragma mark Orientation
+
+- (UIInterfaceOrientation)currentDeviceOrientation
+{
+ UIInterfaceOrientation orientation;
+
+ if ([UIApplication isM13AppExtension]) {
+ if ([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
+ orientation = UIInterfaceOrientationPortrait;
+ } else {
+ orientation = UIInterfaceOrientationLandscapeLeft;
+ }
+ } else {
+ orientation = [UIApplication safeM13SharedApplication].statusBarOrientation;
+ }
+
+ return orientation;
+}
+
+#pragma mark Drawing
+
+- (void)showProgress
+{
+ UIView *progressView = [self getProgressView];
+ UIView *backgroundView = [self getBackgroundView];
+
+ [UIView animateWithDuration:.1 animations:^{
+ progressView.alpha = 1;
+ backgroundView.alpha = 1;
+ }];
+
+ [self setIsShowingProgressBar:YES];
+}
+
+- (void)updateProgress
+{
+ [self updateProgressWithInterfaceOrientation:[self currentDeviceOrientation]];
+}
+
+- (void)updateProgressWithInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ //Create the progress view if it doesn't exist
+ UIView *progressView = [self getProgressView];
+ if(!progressView)
+ {
+ progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 2.5)];
+ progressView.clipsToBounds = YES;
+ [self setProgressView:progressView];
+ }
+
+ if ([self getPrimaryColor]) {
+ progressView.backgroundColor = [self getPrimaryColor];
+ } else {
+ progressView.backgroundColor = self.navigationBar.tintColor;
+ }
+
+ //Create background view if it doesn't exist
+ UIView *backgroundView = [self getBackgroundView];
+ if (!backgroundView)
+ {
+ backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 2.5)];
+ backgroundView.clipsToBounds = YES;
+ [self setBackgroundView:backgroundView];
+ }
+
+ if ([self getBackgroundColor]) {
+ backgroundView.backgroundColor = [self getBackgroundColor];
+ } else {
+ backgroundView.backgroundColor = [UIColor clearColor];
+ }
+
+ //Calculate the frame of the navigation bar, based off the orientation.
+ UIView *topView = self.topViewController.view;
+ CGSize screenSize;
+ if (topView) {
+ screenSize = topView.bounds.size;
+ } else {
+ screenSize = [UIScreen mainScreen].bounds.size;
+ }
+ CGFloat width = 0.0;
+ CGFloat height = 0.0;
+ //Calculate the width of the screen
+ if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
+ //Use the maximum value
+ width = MAX(screenSize.width, screenSize.height);
+ if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
+ height = 32.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+ } else {
+ height = 44.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+ }
+ } else {
+ //Use the minimum value
+ width = MIN(screenSize.width, screenSize.height);
+ height = 44.0; //Hate hardcoding values, but autolayout doesn't work, and cant retreive the new height until after the animation completes.
+ }
+
+ //Check if the progress view is in its superview and if we are showing the bar.
+ if (progressView.superview == nil && [self isShowingProgressBar]) {
+ [self.navigationBar addSubview:backgroundView];
+ [self.navigationBar addSubview:progressView];
+ }
+
+ //Layout
+ if (![self getIndeterminate]) {
+ //Calculate the width of the progress view;
+ float progressWidth = (float)width * (float)[self getProgress];
+ //Set the frame of the progress view
+ progressView.frame = CGRectMake(0, height - 2.5, progressWidth, 2.5);
+ } else {
+ //Calculate the width of the progress view
+ progressView.frame = CGRectMake(0, height - 2.5, width, 2.5);
+ }
+ backgroundView.frame = CGRectMake(0, height - 2.5, width, 2.5);
+}
+
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
+{
+ [self updateProgressWithInterfaceOrientation:toInterfaceOrientation];
+ [self drawIndeterminateWithInterfaceOrientation:toInterfaceOrientation];
+}
+
+- (void)drawIndeterminate
+{
+ [self drawIndeterminateWithInterfaceOrientation:[self currentDeviceOrientation]];
+}
+
+- (void)drawIndeterminateWithInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ if ([self getIndeterminate]) {
+ //Get the indeterminate layer
+ CALayer *indeterminateLayer = [self getIndeterminateLayer];
+ if (!indeterminateLayer) {
+ //Create if needed
+ indeterminateLayer = [CALayer layer];
+ [self setIndeterminateLayer:indeterminateLayer];
+ }
+
+ //Calculate the frame of the navigation bar, based off the orientation.
+ CGSize screenSize = [UIScreen mainScreen].bounds.size;
+ CGFloat width = 0.0;
+ //Calculate the width of the screen
+ if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
+ //Use the maximum value
+ width = MAX(screenSize.width, screenSize.height);
+ } else {
+ //Use the minimum value
+ width = MIN(screenSize.width, screenSize.height);
+ }
+
+ //Create the pattern image
+ CGFloat stripeWidth = 2.5;
+ //Start the image context
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(stripeWidth * 4.0, stripeWidth * 4.0), NO, [UIScreen mainScreen].scale);
+ //Fill the background
+ if ([self getPrimaryColor]) {
+ [[self getPrimaryColor] setFill];
+ } else {
+ [self.navigationBar.tintColor setFill];
+ }
+ UIBezierPath *fillPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, stripeWidth * 4.0, stripeWidth * 4.0)];
+ [fillPath fill];
+ //Draw the stripes
+ //Set the stripe color
+ if ([self getSecondaryColor]) {
+ [[self getSecondaryColor] setFill];
+ } else {
+ CGFloat red;
+ CGFloat green;
+ CGFloat blue;
+ CGFloat alpha;
+ [self.navigationBar.barTintColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ //System set the tint color to a close to, but not non-zero value for each component.
+ if (alpha > .05) {
+ [self.navigationBar.barTintColor setFill];
+ } else {
+ [[UIColor whiteColor] setFill];
+ }
+
+ }
+
+ for (int i = 0; i < 4; i++) {
+ //Create the four inital points of the fill shape
+ CGPoint bottomLeft = CGPointMake(-(stripeWidth * 4.0), stripeWidth * 4.0);
+ CGPoint topLeft = CGPointMake(0, 0);
+ CGPoint topRight = CGPointMake(stripeWidth, 0);
+ CGPoint bottomRight = CGPointMake(-(stripeWidth * 4.0) + stripeWidth, stripeWidth * 4.0);
+ //Shift all four points as needed to draw all four stripes
+ bottomLeft.x += i * (2 * stripeWidth);
+ topLeft.x += i * (2 * stripeWidth);
+ topRight.x += i * (2 * stripeWidth);
+ bottomRight.x += i * (2 * stripeWidth);
+ //Create the fill path
+ UIBezierPath *path = [UIBezierPath bezierPath];
+ [path moveToPoint:bottomLeft];
+ [path addLineToPoint:topLeft];
+ [path addLineToPoint:topRight];
+ [path addLineToPoint:bottomRight];
+ [path closePath];
+ [path fill];
+ }
+ //Retreive the image
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ //Set the background of the progress layer
+ indeterminateLayer.backgroundColor = [UIColor colorWithPatternImage:image].CGColor;
+
+ //remove any indeterminate layer animations
+ [indeterminateLayer removeAllAnimations];
+ //Set the indeterminate layer frame and add to the sub view
+ indeterminateLayer.frame = CGRectMake(0, 0, width + (4 * 2.5), 2.5);
+ UIView *progressView = [self getProgressView];
+ [progressView.layer addSublayer:indeterminateLayer];
+ //Add the animation
+ CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
+ animation.duration = .1;
+ animation.repeatCount = HUGE_VALF;
+ animation.removedOnCompletion = YES;
+ animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(- (2 * 2.5) + (width / 2.0), 2.5 / 2.0)];
+ animation.toValue = [NSValue valueWithCGPoint:CGPointMake(0 + (width / 2.0), 2.5 / 2.0)];
+ [indeterminateLayer addAnimation:animation forKey:@"position"];
+ } else {
+ CALayer *indeterminateLayer = [self getIndeterminateLayer];
+ [indeterminateLayer removeAllAnimations];
+ [indeterminateLayer removeFromSuperlayer];
+ }
+}
+
+#pragma mark properties
+
+- (void)setOldTitle:(NSString *)oldTitle
+{
+ objc_setAssociatedObject(self, &oldTitleKey, self.visibleViewController.navigationItem.title, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSString *)getOldTitle
+{
+ return objc_getAssociatedObject(self, &oldTitleKey);
+}
+
+- (void)setDisplayLink:(CADisplayLink *)displayLink
+{
+ objc_setAssociatedObject(self, &displayLinkKey, displayLink, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CADisplayLink *)getDisplayLink
+{
+ return objc_getAssociatedObject(self, &displayLinkKey);
+}
+
+- (void)setAnimationFromValue:(CGFloat)animationFromValue
+{
+ objc_setAssociatedObject(self, &animationFromKey, [NSNumber numberWithFloat:(float)animationFromValue], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getAnimationFromValue
+{
+ NSNumber *number = objc_getAssociatedObject(self, &animationFromKey);
+ return number.floatValue;
+}
+
+- (void)setAnimationToValue:(CGFloat)animationToValue
+{
+ objc_setAssociatedObject(self, &animationToKey, [NSNumber numberWithFloat:(float)animationToValue], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getAnimationToValue
+{
+ NSNumber *number = objc_getAssociatedObject(self, &animationToKey);
+ return number.floatValue;
+}
+
+- (void)setAnimationStartTime:(NSTimeInterval)animationStartTime
+{
+ objc_setAssociatedObject(self, &animationStartTimeKey, [NSNumber numberWithFloat:(float)animationStartTime], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (NSTimeInterval)getAnimationStartTime
+{
+ NSNumber *number = objc_getAssociatedObject(self, &animationStartTimeKey);
+ return number.floatValue;
+}
+
+- (void)setProgress:(CGFloat)progress
+{
+ if (progress > 1.0) {
+ progress = 1.0;
+ } else if (progress < 0.0) {
+ progress = 0.0;
+ }
+ objc_setAssociatedObject(self, &progressKey, [NSNumber numberWithFloat:(float)progress], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ //Draw the update
+ if ([NSThread isMainThread]) {
+ [self updateProgress];
+ } else {
+ //Sometimes UINavigationController runs in a background thread. And drawing is not thread safe.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self updateProgress];
+ });
+ }
+}
+
+- (void)setIsShowingProgressBar:(BOOL)isShowingProgressBar
+{
+ objc_setAssociatedObject(self, &isShowingProgressKey, [NSNumber numberWithBool:isShowingProgressBar], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CGFloat)getProgress
+{
+ NSNumber *number = objc_getAssociatedObject(self, &progressKey);
+ return number.floatValue;
+}
+
+- (CGFloat)getAnimationDuration
+{
+ return .3;
+}
+
+- (void)setProgressView:(UIView *)view
+{
+ objc_setAssociatedObject(self, &progressViewKey, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (UIView *)getProgressView
+{
+ return objc_getAssociatedObject(self, &progressViewKey);
+}
+
+- (void)setBackgroundView:(UIView *)view
+{
+ objc_setAssociatedObject(self, &backgroundViewKey, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (UIView *)getBackgroundView
+{
+ return objc_getAssociatedObject(self, &backgroundViewKey);
+}
+
+
+- (void)setIndeterminate:(BOOL)indeterminate
+{
+ objc_setAssociatedObject(self, &indeterminateKey, [NSNumber numberWithBool:indeterminate], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self updateProgress];
+ [self drawIndeterminate];
+}
+
+- (BOOL)getIndeterminate
+{
+ NSNumber *number = objc_getAssociatedObject(self, &indeterminateKey);
+ return number.boolValue;
+}
+
+- (void)setIndeterminateLayer:(CALayer *)indeterminateLayer
+{
+ objc_setAssociatedObject(self, &indeterminateLayerKey, indeterminateLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (CALayer *)getIndeterminateLayer
+{
+ return objc_getAssociatedObject(self, &indeterminateLayerKey);
+}
+
+- (BOOL)isShowingProgressBar
+{
+ return [objc_getAssociatedObject(self, &isShowingProgressKey) boolValue];
+}
+
+- (void)setPrimaryColor:(UIColor *)primaryColor
+{
+ objc_setAssociatedObject(self, &primaryColorKey, primaryColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self getProgressView].backgroundColor = primaryColor;
+ [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getPrimaryColor
+{
+ return objc_getAssociatedObject(self, &primaryColorKey);
+}
+
+- (void)setSecondaryColor:(UIColor *)secondaryColor
+{
+ objc_setAssociatedObject(self, &secondaryColorKey, secondaryColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getSecondaryColor
+{
+ return objc_getAssociatedObject(self, &secondaryColorKey);
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor
+{
+ objc_setAssociatedObject(self, &backgroundColorKey, backgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [self setIndeterminate:[self getIndeterminate]];
+}
+
+- (UIColor *)getBackgroundColor
+{
+ return objc_getAssociatedObject(self, &backgroundColorKey);
+}
+
+@end
--
Gitblit v1.8.0