自定義控件 -- 點贊動畫效果

《最美有物》中的點贊效果大家可以看下,在簡書上也看到過安卓版本的。分析它的動畫效果划乖,最近,利用自己閑暇時間用OC做了個Demo挤土,先看下Demo運行效果:


程序運行效果.gif
頁面展示及注意:
  • 默認都是白色琴庵,并且也都是默認圖片。
  • 當點擊某一個視圖時候仰美,兩個表情都要上升迷殿,利用時間也一樣。下降也一樣咖杂。
  • 點擊一個視圖庆寺,背景設置為黃色,另一個表情圖片還原為默認圖片诉字,背景設置成白色懦尝。
  • 點擊之后再下降到最初位置的image是動畫中最后一張image。
  • 占比發(fā)生改變壤圃,占比字樣隨著PLSmileView高度變化而變化陵霉,其字樣透明度也在不斷發(fā)生變化。占比字樣的NSTextAlignmentCenter設置埃唯。
  • 大背景PLBackView的透明度也在變化撩匕。
  • “喜歡”被點擊之后,上升到最高點時候墨叛,會有個星星閃爍止毕。
大背景文件: PLBackView.h 和 PLBackView.m
笑臉的封裝文件:PLSmileView.h 和 PLSmileView.m

引用:(兩步即可)

1、在控制器視圖添加:
  • 就按例子所說漠趁,計算比例之前就先知道無感人數(shù) \ 喜歡人數(shù) \ 總人數(shù)(無感 + 喜歡)扁凛。

  • DislikeCount:無感人數(shù)

  • likeCount:喜歡人數(shù),比例值在內(nèi)部計算闯传。

  • [[UIColor blackColor] colorWithAlphaComponent:0] 背景透明谨朝,而子視圖不透明。參照:iOS 父子視圖的hidden\Alpha\Opaque\clearColor影響簡介

    // 添加視圖  24是無感的人數(shù)  75是喜歡的人數(shù)
    PLBackView *backView = [PLBackView backViewWithDislikeCount:24 likeCount: 75];
    backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0];
    backView.frame = self.view.bounds;
    [self.view addSubview:backView];
    
2、設置屬性:
  • 因為backView.frame = self.view.bounds;所以字币,相對于控制器view的frame值则披,就是在backView中真正位置。

  • tf: 是添加在控制器view上的文本框

  • disLikeFrame:“無感”frame

  • likeFrame: “喜歡”frame

    // 傳入“無感”視圖的frame  30是tf與“無感”的間距  20是大圖片與“無感”的x方向間距
    backView.disLikeFrame = CGRectMake(CGRectGetMaxX(tf.frame) + 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0);
    
    // 傳入“喜歡”視圖的frame  30是“無感”與“喜歡”之間間距 20是大圖片與“喜歡”的x方向間距
    backView.likeFrame = CGRectMake(CGRectGetMaxX(backView.disLikeFrame)+ 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0);
    

demo地址:PLSmileViewDemo

部分注意點: (具體請看demo代碼)

1洗出、占比計算

在創(chuàng)建PLBackView實例視圖時候士复,傳入了無感 喜歡人數(shù),暫且翩活,用成員變量保存起來阱洪,先不計算各自固定占比。等到菠镇,任何一個笑臉被點擊(點擊那個笑臉人數(shù)+1)的時候冗荸,真正用到動態(tài)占比的時候,直接計算動態(tài)占比利耍。懶加載蚌本!
1.1 保存原始人數(shù)

+ (instancetype)backViewWithDislikeCount:(NSUInteger)disLikeCount likeCount:(NSUInteger)likeCount
{
    PLBackView *bv = [[[NSBundle mainBundle] loadNibNamed:@"PLBackView" owner:nil options:nil] lastObject];
    bv.disLikeCount = disLikeCount;
    bv.likeCount = likeCount;
    bv.clickEnable = YES;

   return bv;
}

1.2 在點擊了任何一個笑臉,或者來回多次點擊時候隘梨,占比要設置為0魂毁,之后 重新獲取。

// 1出嘹、比例清空  從懶加載中  獲取最新的比例,防止 來回點擊喜歡與不喜歡 視圖時候咬崔,占比發(fā)生相應的變化
self.disLikeScale = 0.0;
self.likeScale = 0.0;

// 2税稼、判斷點擊的是無感  還是  喜歡 視圖,相應的人數(shù)+1垮斯,同時郎仆,非點擊的那個視圖 背景填充設置為非黃色,且兜蠕,圖片賦值成最初圖片扰肌。
if (smileView.type == PLSmileViewDislikeType) {
    _likeIV.fillYellowColor = NO;
    // 點擊的是“不喜歡”  人數(shù)加1
    self.disLikeCountMut = self.disLikeCount+1;
    self.likeCountMut = self.likeCount;
    _dislikeIV.maxScaleValue = self.disLikeScale; // 最大值
    // 另一個圖片 還原最初的圖片
    _likeIV.imageName = @"like_normal";
    
}else
{
    _dislikeIV.fillYellowColor = NO;
    // 點擊的是“喜歡”人數(shù)加1
    self.likeCountMut = self.likeCount+1;
    self.disLikeCountMut = self.disLikeCount;
    _likeIV.maxScaleValue = self.likeScale; // 最大值
    _dislikeIV.imageName = @"dislike_normal";
}

// 3、 懶加載---比例小數(shù)點第三位要滿5進1熊杨,0.2475 約等于 0.25
#pragma - lazy
- (CGFloat)disLikeScale
{
   if (!_disLikeScale) {
        _disLikeScale = ((CGFloat)_disLikeCountMut / (_disLikeCountMut + _likeCountMut))+0.005; // 0.2475 約等于 0.25
   }
   return _disLikeScale;
 }
- (CGFloat)likeScale
{
   if (!_likeScale) {
    _likeScale = ((CGFloat)_likeCountMut / (_disLikeCountMut + _likeCountMut))+0.005;  // 0.2475 約等于 0.25
   }
   return _likeScale;
}
2曙旭、上升動畫--定時器

通過定時器使PLSmileView實例視圖的占比scale,從0增加到對應的maxScaleValue(無感maxScaleValue為 _disLikeScale晶府, 喜歡maxScaleValue為_likeScale)桂躏。上升是共同的時間,下降也是川陆,利用時間相同剂习,這就需要算出,各自變化的幅度是多少。

1鳞绕、找出高低各自對應的幅度值
CGFloat addOffsetMin = 0.01;
CGFloat addOffsetMax = 0.0;
// 循環(huán)次數(shù)
NSUInteger count = 0;

CGFloat minScale = MIN(self.disLikeScale, self.likeScale);
count = minScale / addOffsetMin;
addOffsetMax = (1 - minScale) / count;
self.count = count;
self.addOffsetMax = addOffsetMax;
self.addOffsetMin = addOffsetMin;
//開始上升 傳scale
__block CGFloat disLikeScale0 = 0.0;
__block CGFloat likeScale0 = 0.0;
[NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) {
    
    if (self.disLikeScale < self.likeScale) {  // 喜歡較高 addOffsetMax屬于喜歡
        
        disLikeScale0 += addOffsetMin;
        likeScale0 += addOffsetMax;
    }else{         // 不喜歡較高 addOffsetMax屬于不喜歡
        
        disLikeScale0 += addOffsetMax;
        likeScale0 += addOffsetMin;
    }
    
    // 傳遞比例  不斷上升
    _dislikeIV.scale = disLikeScale0;
    _likeIV.scale = likeScale0;
    
    
    // 字體的alpha變化
    self.fontAlpha += (CGFloat)1/count;
    // 不斷上升的過程中  比例字數(shù)位置 也在不斷上升
    [self setNeedsDisplay];
    
    
    // 上升到最高點就停止計時器
    if (disLikeScale0 >= _disLikeScale && [timer isValid]) {
        [timer invalidate];
        timer = nil;
        
        
    }
  
    
}];

2失仁、在PLSmileView.m內(nèi)
/// 不斷改變的比例
- (void)setScale:(CGFloat)scale
{
    _scale  = scale;

  // 高度 y值隨著變化
   self.height = (scale <= 0?_originalH:_originalH + MAXHEIGHT * scale);
   self.y = _originalY - MAXHEIGHT * scale;
   // 繪制
   [self setNeedsDisplay];
}
3、PLsmileView實例視圖上升--[self setNeedsDisplay];
1们何,畫背景圓角矩形框  self.color指填充的顏色
 if (_scale == 0) {
    self.color = [UIColor whiteColor];
}

// 畫實心背景 圓角邊框
UIBezierPath *borderB = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.width * 0.5];
borderB.lineWidth = 5;  // 邊框?qū)挾?[self.color setFill];
[[UIColor greenColor] setStroke]; // 描邊顏色
[borderB fill];
[borderB stroke];

// 哭臉  與  笑臉  imageView 始終處在頂端  2.5是表情imageView 與 其父視圖self的y值差距(imageView是addSubview到self上的)
self.imageIv.centerX = self.width * 0.5;
self.imageIv.y = 2.5;
4萄焦、 imageView圖片改變

imageView圖片不斷改變形成動畫,圖片不多的情況下可以使用animationImages垂蜗,在圖片比較多的情況下楷扬,這種方式不會自動清理image,所以 使用了了NSTimer

   // “喜歡”的動畫    總27張
    __block int i = 0;
    [NSTimer scheduledTimerWithTimeInterval:0.02 repeats:YES block:^(NSTimer * _Nonnull timer) {
        i++;
        self.imageIv.image = [UIImage imageNamed:[NSString stringWithFormat:@"like_%d", (i + 1)]];
        
        if ((i+1 == 27) && [timer isValid]) {  // NStimer停止
            [timer invalidate];
            timer = nil;
        }
    }];
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贴见,一起剝皮案震驚了整個濱河市烘苹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌片部,老刑警劉巖镣衡,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異档悠,居然都是意外死亡廊鸥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門辖所,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惰说,“玉大人,你說我怎么就攤上這事缘回∵菏樱” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵酥宴,是天一觀的道長啦吧。 經(jīng)常有香客問我,道長拙寡,這世上最難降的妖魔是什么授滓? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮肆糕,結果婚禮上般堆,老公的妹妹穿的比我還像新娘。我一直安慰自己诚啃,他們只是感情好郁妈,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绍申,像睡著了一般噩咪。 火紅的嫁衣襯著肌膚如雪顾彰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天胃碾,我揣著相機與錄音涨享,去河邊找鬼。 笑死仆百,一個胖子當著我的面吹牛厕隧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俄周,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吁讨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了峦朗?” 一聲冷哼從身側響起建丧,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎波势,沒想到半個月后翎朱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡尺铣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年拴曲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凛忿。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡澈灼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出店溢,到底是詐尸還是另有隱情蕉汪,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布逞怨,位于F島的核電站,受9級特大地震影響福澡,放射性物質(zhì)發(fā)生泄漏叠赦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一革砸、第九天 我趴在偏房一處隱蔽的房頂上張望除秀。 院中可真熱鬧,春花似錦算利、人聲如沸册踩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暂吉。三九已至胖秒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慕的,已是汗流浹背阎肝。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肮街,地道東北人风题。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像嫉父,于是被迫代替她去往敵國和親沛硅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

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