自己畫一個活動指示器

蘋果的UI控件中有一個UIActivityIndicatorView,俗稱菊花×认→_→
現(xiàn)在我們仿照它來制作一個其它樣式的指示器,如下:

ActivityView.png

自定義指示器

首先畫一個白色的扇形关霸。
創(chuàng)建一個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);
}

之后創(chuàng)建一個MyActiveView類繼承自UIView,把上面創(chuàng)建的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);
        // 調(diào)用layer的drawInContext:進(jìn)行繪圖
        [layer setNeedsDisplay];
        // 設(shè)置2倍比率膘掰,防止邊緣出現(xiàn)鋸齒
        layer.contentsScale = 2;
        // 透明
        layer.opacity = 0;
        // 設(shè)置錨點
        layer.anchorPoint = CGPointMake(0.5, 0);
        // 設(shè)置第一個扇形layer的位置
        layer.position = CGPointMake(self.bounds.size.width/2, 0);
        [repLayer addSublayer:layer];
    
        // 設(shè)置透明度漸變的動畫
        opacityAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
        // 透明度從1變?yōu)?
        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;
        // 復(fù)制8個
        repLayer.instanceCount = count;
        // 繞z軸每隔angle角度復(fù)制一個
        repLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1);
        // 復(fù)制子層動畫延遲時長
        repLayer.instanceDelay = duration / count;
    
        // 此視圖繞z軸旋轉(zhuǎn)22度
        CATransform3D transform = CATransform3DRotate(self.layer.transform, 22*M_PI/180, 0, 0, 1);
        self.layer.transform = transform;
    
        // 監(jiān)聽App進(jìn)入前后臺
        [[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];
}

接下來就可以創(chuàng)建使用了。記得把視圖控制器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搞定!旋轉(zhuǎn)吧苍日,小菊花惭聂!(? ??_??)?

ActiveView.gif

CAReplicatorLayer

使用CAReplicatorLayer可以創(chuàng)建出很多類似的重復(fù)動畫效果,比如:

ActiveViews.gif

這些都是常見的指示器效果相恃,它們的代碼如下:

條形指示器

創(chuàng)建一個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等分之后創(chuàng)建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;
        // 每次重復(fù)效果跟上次相反
        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];
環(huán)形指示器

創(chuàng)建一個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;
        // 設(shè)置子層總數(shù)
        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來創(chuàng)建固翰,只需要用CAShapeLayer結(jié)合貝塞爾曲線畫個圓就行狼纬。

Round.gif

代碼如下:

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        // 設(shè)置直徑為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;
}

先介紹以上幾種指示器,如果有比較好看的新的指示器骂际,我會繼續(xù)更新疗琉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市歉铝,隨后出現(xiàn)的幾起案子盈简,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柠贤,死亡現(xiàn)場離奇詭異香浩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)臼勉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門邻吭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宴霸,你說我怎么就攤上這事镜盯。” “怎么了猖败?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長降允。 經(jīng)常有香客問我恩闻,道長,這世上最難降的妖魔是什么剧董? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任幢尚,我火速辦了婚禮,結(jié)果婚禮上翅楼,老公的妹妹穿的比我還像新娘尉剩。我一直安慰自己,他們只是感情好毅臊,可當(dāng)我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布理茎。 她就那樣靜靜地躺著,像睡著了一般管嬉。 火紅的嫁衣襯著肌膚如雪皂林。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天蚯撩,我揣著相機(jī)與錄音础倍,去河邊找鬼。 笑死胎挎,一個胖子當(dāng)著我的面吹牛沟启,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播犹菇,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼德迹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了项栏?” 一聲冷哼從身側(cè)響起浦辨,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后流酬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體币厕,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年芽腾,在試婚紗的時候發(fā)現(xiàn)自己被綠了旦装。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡摊滔,死狀恐怖阴绢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情艰躺,我是刑警寧澤呻袭,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站腺兴,受9級特大地震影響左电,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜页响,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一篓足、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闰蚕,春花似錦栈拖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盼玄,卻和暖如春染簇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背强岸。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工锻弓, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝌箍。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓青灼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親妓盲。 傳聞我的和親對象是個殘疾皇子杂拨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件悯衬、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,120評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,293評論 25 707
  • 代替catch ``由于 catch 標(biāo)識符可能會導(dǎo)致問題出現(xiàn)弹沽,因此一些類庫(Library)也采用了 caugh...
    許道龍閱讀 1,255評論 0 0
  • 今天要講述的,是我跟四歲小兒斗智斗勇的故事丽已。為了大家看得明白蚌堵,簡單介紹小主人公:小名桐桐,性別女沛婴,年齡四歲吼畏,幼兒園...
    我本卿狂閱讀 517評論 0 0
  • 星期天下午 我熟悉的飯館門口 貼著 內(nèi)部裝修 我踱到另外一條街上 隨便進(jìn)了一家面館 意外的發(fā)現(xiàn) 那里有 全市最好的...
    老晁閱讀 247評論 0 1