概述

根据UIBezierPath和CAShapeLayer自定义倒计时进度条,适用于app启动的时候设置一个倒计时关闭启动页面。可以设置进度条颜色,填充颜色,进度条宽度以及点击事件等。

详细

我们都知道 APP启动时加载的是LaunchImage 这张静态图。现在好多应用启动时都是动态的,并且右上角可选择跳过。

这里介绍一下自己在做这种动画时的一种方案。

启动图依然是加载的,只不过是一闪而过,这时候我想到的是拿到当前的LaunchImage图片,然后进行处理,造成一种改变了LaunchImage动画的假象。

思路如下:

根据UIBezierPath和CAShapeLayer自定义倒计时进度条,适用于app启动的时候设置一个倒计时关闭启动页面。可以设置进度条颜色,填充颜色,进度条宽度以及点击事件等。

一、设置跳过按钮

ZLDrawCircleProgressBtn.h:

/**
* set complete callback
*
* @param lineWidth line width
* @param block block
* @param duration time
*/
- (void)startAnimationDuration:(CGFloat)duration withBlock:(DrawCircleProgressBlock )block;

ZLDrawCircleProgressBtn.m :

先初始化相关跳过按钮及进度圈:

// 底部进度条圈
@property (nonatomic, strong) CAShapeLayer *trackLayer;
// 表层进度条圈
@property (nonatomic, strong) CAShapeLayer *progressLayer;
@property (nonatomic, strong) UIBezierPath *bezierPath;
@property (nonatomic, copy) DrawCircleProgressBlock myBlock;
- (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.0f;
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;
// 底部圈色
_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;
// 进度条圈进度色
_progressLayer.strokeColor = self.progressColor.CGColor ? self.progressColor.CGColor : [UIColor colorWithRed:197/255.0 green:159/255.0 blue:82/255.0 alpha:1].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:pathAnimation forKey:nil]; _progressLayer.path = _bezierPath.CGPath;
}
return _progressLayer;
}

设置代理回调:

#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];
}

二、启动页

ZLStartPageView.h :

露出 显示引导页面方法:

/**
* 显示引导页面方法
*/
- (void)show;

ZLStartPageView.m :

  1. 初始化启动页

// 启动页图
@property (nonatomic,strong) UIImageView *imageView;
// 跳过按钮
@property (nonatomic, strong) ZLDrawCircleProgressBtn *drawCircleBtn;
- (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]; // 2.跳过按钮
ZLDrawCircleProgressBtn *drawCircleBtn = [[ZLDrawCircleProgressBtn alloc]initWithFrame:CGRectMake(kscreenWidth - 55, 30, 40, 40)];
drawCircleBtn.lineWidth = 2;
[drawCircleBtn setTitle:@"跳过" 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;
}

2. 显示启动页且完成时候回调移除

- (void)show {
// progress 完成时候的回调
__weak __typeof(self) weakSelf = self;
[weakSelf.drawCircleBtn startAnimationDuration:showtime withBlock:^{
[weakSelf removeProgress];
}]; UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:self];
}

3. 移除启动页面

- (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];
}];
}

三、动态启动页的显示代码放在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]; return YES;
}

设置启动页:

- (void)setupStartPageView {

    ZLStartPageView *startPageView = [[ZLStartPageView alloc] initWithFrame:self.window.bounds];
[startPageView show];
}

这个时候就可以可以测试喽~

四、压缩文件截图

界面性问题可以根据自己项目需求调整即可, 具体可参考代码, 项目能够直接运行!

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

iOS-启动动态页跳过设计思路的更多相关文章

  1. iOS 复杂tableView的 cell一般设计思路

  2. iOS 组件化 —— 路由设计思路分析

    原文 前言 随着用户的需求越来越多,对App的用户体验也变的要求越来越高.为了更好的应对各种需求,开发人员从软件工程的角度,将App架构由原来简单的MVC变成MVVM,VIPER等复杂架构.更换适合业 ...

  3. iOS开发:代码通用性以及其规范 第二篇(猜想iOS中实现TableView内部设计思路(附代码),以类似的思想实现一个通用的进度条)

    在iOS开发中,经常是要用到UITableView的,我曾经思考过这样一个问题,为什么任何种类的model放到TableView和所需的cell里面,都可以正常显示?而我自己写的很多view却只是能放 ...

  4. 通过href链接实现从当前页面跳转到动态页的指定页面的实现方式

    指定页的jsp的href设置 <a href="/lekg/check/shangchuan2.jsp?tabtype=2"><li><img src ...

  5. IOS 一句代码搞定启动引导页

    前言引导页,一个酷炫的页面,自从微博用了之后一下就火起来了,对于现在来说一个app如果没有引导页似乎总显那么不接地气,那么为了让我们的app也“高大上”一次,我写了一个demo来实现启动引导页的实现, ...

  6. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...

  7. Redis入门指南(第2版) Redis设计思路学习与总结

    https://www.qcloud.com/community/article/222 宋增宽,腾讯工程师,16年毕业加入腾讯,从事海量服务后台设计与研发工作,现在负责QQ群后台等项目,喜欢研究技术 ...

  8. Redis设计思路学习与总结

    版权声明:本文由宋增宽原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/222 来源:腾云阁 https://www.qclo ...

  9. iOS启动图和开屏广告图,类似网易

    iOS启动图和开屏广告图,类似网易 启动图是在iOS开发过程中必不可少的一个部分,很多app在启动图之后会有一张自定义的开屏广告图,点击该广告图可以跳转到广告图对应的页面.今天呢,和大家分享一下如何添 ...

随机推荐

  1. Android实例剖析笔记(四)

    摘要:分析NoteEditor这个类和以及Content Provider机制 NoteEditor深入分析 首先来弄清楚“日志编辑“的状态转换,通过上篇文章的方法来做下面这样一个实验,首先进入“日志 ...

  2. python测试开发django-6.模板中include使用

    前言 当我们打开一个网站的时候,在打开不同的页面时候,会发现每个页面的顶部.底部内容都差不多,这样就可以把这些公共的部分,单独抽出来. 类似于python里面的函数,把公共部分写成函数,然后调用就行了 ...

  3. NGUI 3.5教程(一)安装NGUI 3.5.8

    写在前面: 网上找的NGUI教程,都是基于2.x版本号的.为了能配合教程学着做,我也是下载了各种NGUI 2.x版本号.可是在导入的时候,或多或少都报错(我用的Unity 的版本号是4.3.2).无奈 ...

  4. c3p0、dbcp、proxool、BoneCP比较

    1.1 测试环境: 操作系统:windows xp sp3 数据库:mysql 5.1 1.2 测试条件: initialSize=30; maxSize=200; minSize=30; 其余参数为 ...

  5. Log4j输出格式控制

    参数说明例子 %c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间 log4j配置文件参数举例 输出显示媒介 假设当前logger名字空间是& ...

  6. FFmpeg的H264编码有内存泄漏吗??!!!

    靠,内存泄漏好严重.开始怀疑是自己代码问题,调试了半天,又反复改写和优化代码,还是泄漏严重. 拿网上现成的FFMPEG H264编码的范例来测试,同样泄漏很严重. 百度了一下,有很多人遇到同样的问题, ...

  7. [Web前端]由cookies安全说开去

    在Web应用中,Cookie很容易成为安全问题的一部分.从以往的经验来看,对Cookie在开发过程中的使用,很多开发团队并没有形成共识或者一定的 规范,这也使得很多应用中的Cookie成为潜在的易受攻 ...

  8. Java基础(十四):泛型

    一.Java 泛型: Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就 ...

  9. 【Python】Django数据模型、级联删除、级联更新、ER图导出等

    在本文中,我们将向读者详细介绍如何在更新和删除父表数据的同时,触发有关子表数据的级联更新和删除操作.您将看到当使用InnoDB表的时候,借助于外键约束就可以轻松搞定这一过程. 一.利用外键约束更新并删 ...

  10. 如何利用SQL语句求日期的时间差值,并汇总网上的一些信息

    MySQL本身提供了 DATEDIFF 函数,用来计算时间差. 手册:http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.ht ...