自己画一个ActivityIndicatorView-b
苹果的UI控件中有一个UIActivityIndicatorView,俗称菊花。→_→
现在我们仿照它来制作一个其它样式的指示器,如下:
ActivityView.png
自定义指示器
首先画一个白色的扇形。
创建一个MyLayer类继承自CALayer,重写它的绘图方法- (void)drawInContext:(CGContextRef)ctx:
- (void)drawInContext:(CGContextRef)ctx {
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1);
CGContextMoveToPoint(ctx, CGRectGetMaxX(self.bounds)/2, CGRectGetMaxY(self.bounds)); // 顺时针从-70度画到-110度 (0度是3点钟方向)
CGContextAddArc(ctx, CGRectGetMaxX(self.bounds)/2, CGRectGetMaxY(self.bounds), 20, -70 * M_PI / 180, -110 * M_PI / 180, 1); CGContextClosePath(ctx); CGContextDrawPath(ctx, kCGPathFillStroke);
}
之后创建一个MyActiveView类继承自UIView,把上面创建的layer添加到MyActiveView上。
@implementation MyActiveView{
MyLayer *layer;
CABasicAnimation *opacityAnim;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
CAReplicatorLayer *repLayer = [CAReplicatorLayer layer];
repLayer.frame = self.bounds;
[self.layer addSublayer:repLayer]; // 画一个扇形的layer
layer = [MyLayer layer];
layer.frame = CGRectMake(0, 0, 22, 22); // 调用layer的drawInContext:进行绘图
[layer setNeedsDisplay]; // 设置2倍比率,防止边缘出现锯齿
layer.contentsScale = 2; // 透明
layer.opacity = 0; // 设置锚点
layer.anchorPoint = CGPointMake(0.5, 0); // 设置第一个扇形layer的位置
layer.position = CGPointMake(self.bounds.size.width/2, 0);
[repLayer addSublayer:layer]; // 设置透明度渐变的动画
opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"]; // 透明度从1变为0
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0];
opacityAnim.removedOnCompletion = YES;
opacityAnim.repeatCount = MAXFLOAT;
CGFloat duration = 0.7;
opacityAnim.duration = duration;
[layer addAnimation:opacityAnim forKey:nil];
int count = 8;
CGFloat angle = M_PI * 2 / count; // 复制8个
repLayer.instanceCount = count; // 绕z轴每隔angle角度复制一个
repLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1); // 复制子层动画延迟时长
repLayer.instanceDelay = duration / count; // 此视图绕z轴旋转22度
CATransform3D transform = CATransform3DRotate(self.layer.transform, 22*M_PI/180, 0, 0, 1); self.layer.transform = transform; // 监听App进入前后台
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stop) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(start) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
// 停止动画
- (void)stop {
[layer removeAllAnimations];
}
// 开始动画
- (void)start {
[layer addAnimation:opacityAnim forKey:nil];
}
接下来就可以创建使用了。记得把视图控制器view的白色改为其它颜色,否则你是看不到这个白色指示器的。
MyActiveView *activityView = [[MyActiveView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2-25, self.view.bounds.size.height-200, 50, 50)];
[self.view addSubview:activityView];
OK搞定!旋转吧,小菊花!(ง •̀_•́)ง
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="" data-ratio="1.7857142857142858" data-src="http://mmbiz.qpic.cn/mmbiz_gif/g4uoJOMA38IaGo10L2N0W1ZsUiaJ9CSGCwNPRIJnL18Z7wRibcVIibcAu7udm5809XibsONhIODQDSOK2EsjXExVCQ/0?wx_fmt=gif" data-type="gif" data-w="224" />
ActiveView.gif
CAReplicatorLayer
使用CAReplicatorLayer可以创建出很多类似的重复动画效果,比如:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="" data-ratio="0.5811965811965812" data-src="http://mmbiz.qpic.cn/mmbiz_gif/g4uoJOMA38IaGo10L2N0W1ZsUiaJ9CSGCPGqaLVOibMQSBibofY6PQUIGN0ibSVLG2se7n0CVCdwqbiawV3ae0Aw0XA/0?wx_fmt=gif" data-type="gif" data-w="234" />
ActiveViews.gif
这些都是常见的指示器效果,它们的代码如下:
条形指示器
创建一个ActiveView1类,继承自UIView。
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
CAReplicatorLayer *repLayer = [CAReplicatorLayer layer];
repLayer.frame = self.bounds;
[self.layer addSublayer:repLayer];
CALayer *layer = [CALayer layer]; // 宽度5等分之后创建3个repLayer
CGFloat width = frame.size.width/5;
CGFloat height = frame.size.height;
layer.bounds = CGRectMake(0, 0, width, height); // 第一个layer的位置
layer.position = CGPointMake(width/2, height/2);
layer.backgroundColor = [UIColor greenColor].CGColor;
[repLayer addSublayer:layer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
animation.fromValue = @1;
animation.toValue = @0.3;
animation.duration = 0.4; // 每次重复效果跟上次相反
animation.autoreverses = YES;
animation.repeatCount = CGFLOAT_MAX;
[layer addAnimation:animation forKey:nil];
repLayer.instanceCount = 3;
repLayer.instanceDelay = 0.2; // x轴上每隔self.frame.size.width/5*2距离,放置一个repLayer
repLayer.instanceTransform = CATransform3DMakeTranslation(frame.size.width/5*2, 0, 0);
}
return self;
}
在控制器中添加它即可:
ActiveView1 *view1 = [[ActiveView1 alloc] initWithFrame:CGRectMake(20, 200, 70, 50)];
[self.view addSubview:view1];
环形指示器
创建一个ActiveView2类,继承自UIView。
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
CAReplicatorLayer *repLayer = [CAReplicatorLayer layer];
repLayer.frame = self.bounds;
[self.layer addSublayer:repLayer];
CALayer *layer = [CALayer layer];
layer.bounds = CGRectMake(0, 0, 10, 10);
layer.cornerRadius = 5;
layer.masksToBounds = YES;
layer.transform = CATransform3DMakeScale(0, 0, 0); // 第一个layer的位置
layer.position = CGPointMake(frame.size.width/2, 5);
layer.backgroundColor = [UIColor greenColor].CGColor;
[repLayer addSublayer:layer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = @1;
animation.toValue = @0.2;
CGFloat duration = 1.2;
animation.duration = duration;
animation.repeatCount = CGFLOAT_MAX;
[layer addAnimation:animation forKey:nil]; int count = 12; // 360度分成12份
CGFloat angle = M_PI * 2 / count; // 设置子层总数
repLayer.instanceCount = count;
repLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1);
repLayer.instanceDelay = duration / count;
}
return self;
}
在控制器中添加它:
ActiveView2 *view2 = [[ActiveView2 alloc] initWithFrame:CGRectMake(150, 200, 70, 70)];
[self.view addSubview:view2];
另外一种指示器
除了上面三种指示器,还有一种指示器比较常见,不过它的代码跟上面的不太一样,它不需要使用CAReplicatorLayer来创建,只需要用CAShapeLayer结合贝塞尔曲线画个圆就行。
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="" data-ratio="0.967741935483871" data-src="http://mmbiz.qpic.cn/mmbiz_gif/g4uoJOMA38IaGo10L2N0W1ZsUiaJ9CSGCpZP86JSGclRqDJQ2uTXsoHKiaicXiaWIJ2ic1Kicicuqy7loDl4yibjZANKXQ/0?wx_fmt=gif" data-type="gif" data-w="124" />
Round.gif
代码如下:
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) { // 设置直径为self宽/高的最小值
CGFloat diameter = MIN(frame.size.width, frame.size.height); CAShapeLayer *sLayer = [CAShapeLayer layer];
sLayer.anchorPoint = CGPointMake(0.5, 0.5);
sLayer.frame = CGRectMake(0, 0, diameter, diameter);
sLayer.strokeColor = [UIColor greenColor].CGColor;
sLayer.fillColor = [UIColor clearColor].CGColor;
sLayer.lineWidth = 2;
CGFloat raduis = diameter/2;
UIBezierPath *roundPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(raduis, raduis) radius:raduis startAngle:0 endAngle:(2*M_PI-M_PI_4) clockwise:YES];
sLayer.path = roundPath.CGPath;
[self.layer addSublayer:sLayer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.fromValue = @0;
animation.toValue = @(2*M_PI);
animation.duration = 1.f;
animation.repeatCount = CGFLOAT_MAX;
[sLayer addAnimation:animation forKey:nil];
}
return self;
}
自己画一个ActivityIndicatorView-b的更多相关文章
- Effective前端3:用CSS画一个三角形
p { text-indent: 2em } .triangle-container p { text-indent: 0 } img { margin: 15px 0 } 三角形的场景很常见,打开一 ...
- canvas游戏小试:画一个按方向键移动的圆点
canvas游戏小试:画一个按方向键移动的圆点 自己对canvas,但又有一颗做游戏的心TT.然后记录一下对canvas的学习吧,用一个按方向键控制的小圆点来做练习.(编程时用了一些es6的语法) ...
- PostScript的简单例子-用粗线画一个圆
一 近期需要用到PostScript,查询资料学习PS的语法 简单的画一个圆的例子 %!PS-Adobe-3.0 /inch{72 mul} def 4.25 inch 5.5 inch 1.5 in ...
- Android画一个随意拖动的圆形
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactor ...
- 用PS画一个齿轮
以前只会画圆画方,这没技术含量.今天学了一个稍难一点的,画一个齿轮.图形有圆也有方.以下描述如何画出来的. 一.打开PS准备一画布,画一矩形并且填充颜色. 二.编辑->自由变换(CTRL+T), ...
- 深夜,用canvas画一个时钟
深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...
- Directx11学习笔记【十二】 画一个旋转的彩色立方体
上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...
- Directx11学习笔记【十一】 画一个简单的三角形--effect框架的使用
这里不再介绍effect框架的具体使用,有关effect框架使用可参考http://www.cnblogs.com/zhangbaochong/p/5475961.html 实现的功能依然是画一个简单 ...
- css3简单几步画一个乾坤图
原文:[原创]css3简单几步画一个乾坤图 效果如上,鼠标移上去会有动画. 代码如下非常简单: <html> <head> <style> .outer{heigh ...
随机推荐
- Xcode文件目录选中变成白色, 解决方案
新版Xcode很不稳定, 有时候被选中文件变成白色, 看着很不舒服, 以前都是毫无办法, 等它自动变回来, 现在有一个解决办法, 点击文件目录上面的选项, 随便切换一个再切换回来, 发现文件目录颜色回 ...
- 安装MySQL在最后的start service停住了解决方法
今天自己安装mysql在start service卡住了,原来是以前安装过,但是没有删干净.通过下面的方法解决了,特分享下 由于我的MySQL不知道什么原因突然打不开了并报了个10061的错,查了下原 ...
- C#一些小知识点
1. 在Load时候由代码来做控件PictureBox,并且用代码将图片加载进去: private void Form2_Load(object sender, EventArgs e) { Dire ...
- CentOS下安装福昕PDF软件
官方下载地址:http://www.foxitsoftware.cn/downloads/ tar -jxvf foxreader.tar.bz2问题:下载官方包以后解压,双击不能打开,也没有任何提示 ...
- Android的几种alert对话框
@Override public void onClick(View v) { switch (v.getId()) { case R.id.d1: AlertDialog.Builder build ...
- [MSDN]使用 REST 处理文件夹和文件
msdn: http://msdn.microsoft.com/zh-cn/library/dn292553.aspx 了解如何使用 SharePoint 2013 REST 界面对文件夹和文件执行基 ...
- createjs 使用记录
createjs由几个库组成: l,easeljs,这个是核心,包括了显示列表.事件机制: 2,preloadjs,用于预加载图片等: 3,tweenjs,用于控制元件的缓动: 4,soundjs,用 ...
- ASP伪静态页面(不需要通过iis+ISAPI_Rewrite)
很简单的教程,献给喜欢SEO的朋友们. 不需要通过iis+ISAPI_Rewrite做基于IIS的url rewrite 一.数据库很简单使用ACCESS,Data.mdb建立一个表Article,三 ...
- hdoj1584 蜘蛛牌 (区间型动态规划)
hdoj1584 分析: f[i][j] 表示 把一串牌 牌 i 到 j 摞为一摞时 所花费最少的步数. d[i][j] 表示把牌 i 挪到牌 j 上时需要走的步数(最初给的状态). 以一串牌 3~8 ...
- SQL server 数据库日志文件过大清空日志文件
SQL2008:'在SQL2008中清除日志就必须在简单模式下进行,等清除动作完毕再调回到完全模式. USE [master] GO ALTER DATABASE DBName SET RECOVER ...