We all know that the APP launches with a static image of LaunchImage. Many apps now start dynamically and skip in the upper right corner. Screenshot below:
Here is a way to do this kind of animation. The LaunchImage is still loaded, just a flash, and what I want to do is take the current LaunchImage image and manipulate it to give the illusion of changing the LaunchImage animation.
The idea is as follows: Customize the countdown progress bar according to UIBezierPath and CAShapeLayer, which is suitable for setting a countdown close startup page when the app starts. You can set progress bar color, fill color, progress bar width and click events.
Set skip button
ZLDrawCircleProgressBtn.h :
// Skip the button#import <UIKit/UIKit.h>
typedef void(^DrawCircleProgressBlock)(void);
@interface ZLDrawCircleProgressBtn : UIButton
//set track color
@property (nonatomic, strong) UIColor *trackColor;
//set progress color
@property (nonatomic, strong) UIColor *progressColor;
//set track background color
@property (nonatomic, strong) UIColor *fillColor;
//set progress line width
@property (nonatomic, assign) CGFloat lineWidth;
//setprogress duration @property (nonatomic, assign) CGFloat animationDuration; / * * *set complete callback
*
* @param lineWidth line width
* @param block block
* @param duration time
*/
- (void)startAnimationDuration:(CGFloat)duration withBlock:(DrawCircleProgressBlock )block;
@end
Copy the code
ZLDrawCircleProgressBtn. M: initialize the skip button and progress
#import "ZLDrawCircleProgressBtn.h"
#define degreesToRadians(x) ((x) * M_PI / 180.0)@property (nonatomic, strong) CAShapeLayer *trackLayer; @property (nonatomic, strong) CAShapeLayer *progressLayer; @property (nonatomic, strong) UIBezierPath *bezierPath; @property (nonatomic, copy) DrawCircleProgressBlock myBlock; @end @implementation ZLDrawCircleProgressBtn - (instancetype)initWithFrame:(CGRect)frame {if (self == [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
[self.layer addSublayer:self.trackLayer];
}
return self;
}
- (UIBezierPath *)bezierPath {
if(! _bezierPath) {CGFloat width = CGRectGetWidth(self.frame)/2.0f; CGFloat height = CGRectGetHeight (self. Frame) / 2.0 f; CGPoint centerPoint = CGPointMake(width, height);float radius = CGRectGetWidth(self.frame)/2;
_bezierPath = [UIBezierPath bezierPathWithArcCenter:centerPoint
radius:radius
startAngle:degreesToRadians(-90)
endAngle:degreesToRadians(270)
clockwise:YES];
}
return _bezierPath;
}
- (CAShapeLayer *)trackLayer {
if(! _trackLayer) { _trackLayer = [CAShapeLayer layer]; _trackLayer.frame = self.bounds; _tracklayer.fillcolor = self.fillcolor.cgcolor? self.fillColor.CGColor : [UIColor clearColor].CGColor ; _trackLayer.lineWidth = self.lineWidth ? self.lineWidth : 2.f; // Bottom circle color _tracklayer.strokecolor = self.trackcolor.cgcolor? Self.trackcolor.cgcolor: [UIColor colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:0.3].cgcolor; _trackLayer.strokeStart = 0.f; _trackLayer.strokeEnd = 1.f; _trackLayer.path = self.bezierPath.CGPath; }return _trackLayer;
}
- (CAShapeLayer *)progressLayer {
if(! _progressLayer) { _progressLayer = [CAShapeLayer layer]; _progressLayer.frame = self.bounds; _progressLayer.fillColor = [UIColor clearColor].CGColor; _progressLayer.lineWidth = self.lineWidth ? self.lineWidth : 2.f; _progressLayer.lineCap = kCALineCapRound; / / the progress bar circle. Color _progressLayer strokeColor = self. ProgressColor. CGColor? Self. ProgressColor. CGColor: [UIColor colorWithRed: 197/255.0 green: 159/255.0 blue: 82/255.0 alpha: 1) the CGColor; _progressLayer.strokeStart = 0.f; CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = self.animationDuration; PathAnimation. FromValue = @ (0.0); PathAnimation. ToValue = @ (1.0); pathAnimation.removedOnCompletion = YES; pathAnimation.delegate = self; [_progressLayer addAnimation:pathAnimationforKey:nil];
_progressLayer.path = _bezierPath.CGPath;
}
return _progressLayer;
}
Copy the code
Set up the proxy callback
#pragma mark -- CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if(flag) { self.myBlock(); }}#pragma mark ---
- (void)startAnimationDuration:(CGFloat)duration withBlock:(DrawCircleProgressBlock )block {
self.myBlock = block;
self.animationDuration = duration;
[self.layer addSublayer:self.progressLayer];
}
Copy the code
### c: start page zlStartPageView. h: display the bootpage method
/ / start page#import <UIKit/UIKit.h>
#define kscreenWidth [UIScreen mainScreen].bounds.size.width@interface ZLStartPageView: UIView /** * - (void)show; @endCopy the code
Zlstartpageview. m: 1. Initialize the start page
#import "ZLStartPageView.h"
#import "ZLDrawCircleProgressBtn.h"@property (nonatomic,strong) UIImageView *imageView; @property (nonatomic, strong) ZLDrawCircleProgressBtn *drawCircleBtn; Static int const showtime = 3; @implementation ZLStartPageView - (instancetype)initWithFrame:(CGRect)frame {if(self = [super initWithFrame:frame]) { // 1. Imageview = [[UIImageView alloc]initWithFrame:frame]; _imageView.contentMode = UIViewContentModeScaleAspectFill; _imageView.image = [UIImage imageNamed:@"LaunchImage_667h"]; [self addSubview:_imageView]; // skip the button ZLDrawCircleProgressBtn *drawCircleBtn = [[ZLDrawCircleProgressBtn alloc]initWithFrame:CGRectMake(kscreenWidth -55, 30, 40, 40)]; drawCircleBtn.lineWidth = 2; [drawCircleBtnsetTitle:@"Skip" forState:UIControlStateNormal];
[drawCircleBtn setTitleColor:[UIColor colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:1] forState:UIControlStateNormal];
drawCircleBtn.titleLabel.font = [UIFont systemFontOfSize:14];
[drawCircleBtn addTarget:self action:@selector(removeProgress) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:drawCircleBtn];
self.drawCircleBtn = drawCircleBtn;
}
return self;
}
Copy the code
2. Display the startup page and remove the callback when complete
- (void)show {// progress complete when the callback __weak __typeof(self) weakSelf = self; [weakSelf.drawCircleBtn startAnimationDuration:showtime withBlock:^{ [weakSelf removeProgress]; }]; UIWindow *window = [UIApplication sharedApplication].keyWindow; [window addSubview:self]; }Copy the code
3. Remove the startup page
/ / remove the start page - (void) removeProgress {self. ImageView. Transform = CGAffineTransformMakeScale (1, 1); self.imageView.alpha = 1; [UIView animateWithDuration: 0.3 animations: ^ {self. DrawCircleBtn. Hidden = NO; self. ImageView. Alpha = 0.05; self.imageView.transform = CGAffineTransformMakeScale(5, 5); } completion:^(BOOL finished) { self.drawCircleBtn.hidden = YES; [self.imageView removeFromSuperview]; }]; }Copy the code
The display code for the dynamic launch page is placed in AppDeleate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[HomeViewController alloc] init]];
[self.window makeKeyAndVisible];
[self setupStartPageView];
returnYES; } /** * setupStartPageView {ZLStartPageView *startPageView = [[ZLStartPageView alloc] initWithFrame:self.window.bounds]; [startPageView show]; }Copy the code
This time can be tested, the effect is as follows:
If you want to start page loading ads, please go to ios-app to start page loading ads