自己画一个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搞定!旋转吧,小菊花!(? •?_•?)?

ActiveView.gif

CAReplicatorLayer

使用CAReplicatorLayer可以创建出很多类似的重复动画效果,比如:

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结合贝塞尔曲线画个圆就行。

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;
}
时间: 2024-10-16 12:50:10

自己画一个ActivityIndicatorView-b的相关文章

Effective前端3:用CSS画一个三角形

三角形的场景很常见,打开一个页面可以看到各种各样的三角形: 由于div一般是四边形,要画个三角形并不是那么直观.你可以贴一张png,但是这种办法有点low,或者是用svg的形式,但是太麻烦.三角形其实可以用CSS画出来.如上图提到,可以分为两种三角形,一种是纯色的三角形,第二种是有边框色的三角形,先介绍最简单的纯色三角形. 1. 三角形的画法 三角形可以用border画出来,首先一个有四个border的div应该是这样的: 然后把它的高度和宽度去掉,剩下四个border,就变成了: 再把bord

Directx11学习笔记【十二】 画一个旋转的彩色立方体

上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体中加入颜色变量 struct Vertex { XMFLOAT3 pos; XMFLOAT4 color; }; 着色器代码 1 cbuffer cbPerObject 2 { 3 float4x4 gWorldViewProj; 4 }; 5 6 struct VertexIn 7 { 8 flo

[原创]css3简单几步画一个乾坤图

效果如上,鼠标移上去会有动画. 代码如下非常简单: 1 <html> 2 <head> 3 <style> 4 .outer{height:100px;width:200px;border-radius:100px 100px 0px 0px;border:solid 1px #666;border-bottom:none; margin:0 auto;background:#fff;overflow:hidden;} 5 .inner{width:300px;heig

智慧城市,在中国的北海边再画一个圈——大连“中国首届智慧城市协同创新峰会”请你带好笔

这可能是中国第二次大规模地改变城市印象.从1979年,"在中国的南海边画了一个圈",用三十多年的时间,中国完成了从传统城市到现代城市的跨越,繁荣.机会.财富.梦想演变成激动人心的中国奇迹和城市骄傲.但随之而来,城市化进程也引发诸多的问题,社会保险.医疗.就业.安防.交通--所有的这些问题都为生活于此的每个城居者带来困扰. 现代化的中国城市需要改变,城市的管理需要提升,所有人都在发问,城市未来的发展空间在哪,围绕城市建设,商机在哪?如果城市已经拥有了摩天大楼.地铁公交.城际轻轨.繁华商铺

看opengl 写代码(4) 画一个圆

opengl 编程指南 P30 下面代码 是 用 直线 连起来 画一个圆. // circle.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <gl/glut.h> #include <cmath> #define LENGTH 100 #define PI 3.1415926 void init(){ glClearColor(0,0,0,0); } void display(){ glColor3f

php画一个背景透明,且开始处旋转到在圆的正下方处的一个圆饼统计图

/* * _survey 得到一个投票的圆饼图 * @access public 表示函数对外公开 * @param $_agree 同意票数 * @param $_disagree 反对票数 * return 一张统计圆饼图 * */ function _vote($_agree,$_disagree){ //处理参数 if($_agree==0&&$_disagree==0){ $_vote = 270; } if($_agree==0&&$_disagree!=0){

手把手带你画一个动态错误提示 Android自定义view

嗯..再差1篇就可以获得持之以恒徽章了,今天带大家画一个比较简单的view. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50477108 废话不多说,看效果图: 首先 构造函数 测量... 这里就一笔带过了. public ErrorView(Context context) { this(context, null); } public ErrorView(Context context, AttributeSet attrs

手把手带你画一个漂亮蜂窝view Android自定义view

上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义view需求. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50554058 本文是和代码同步写的.也就是说在写文章的时候才敲的代码.这样会显得文章有些许混乱.但是我想这样记录下来,一个自定义view的真正的制作过程,是一点一点,一步步跟

css3简单几步画一个乾坤图

原文:[原创]css3简单几步画一个乾坤图 效果如上,鼠标移上去会有动画. 代码如下非常简单: 1 <html> 2 <head> 3 <style> 4 .outer{height:100px;width:200px;border-radius:100px 100px 0px 0px;border:solid 1px #666;border-bottom:none; margin:0 auto;background:#fff;overflow:hidden;} 5 .