QQ粘性效果

動(dòng)畫(huà)分析

  • 當(dāng)前控件既可以顯示圖片,有可以顯示文字,那么我們就可以通過(guò)按鈕來(lái)最為當(dāng)前的控件.
  • 當(dāng)拖動(dòng)控件,當(dāng)前控件尺寸不會(huì)改變,起始位置處會(huì)有一個(gè)同尺寸的控件隨著偏移的距離,逐漸變小.起始位置的控件只是簡(jiǎn)單的用來(lái)顯示,所以這里可以用一個(gè)View來(lái)完成.而2控件中間的紐帶我們可以通過(guò)圖層來(lái)實(shí)現(xiàn).
text.gif

1.搭建界面

  • 從storyboard中創(chuàng)建一個(gè)按鈕,并且自定義一個(gè)繼承自UIButton的類(lèi),修改按鈕的class
  • 在初始化方法中,初始化我們自定義按鈕的屬性
    • 考慮到按鈕分裝重用,將初始化方法抽取出來(lái),分別在awakeFromNibinitWithFrame中實(shí)現(xiàn)
-(void) setUp
{
    self.radius = self.bounds.size.width * 0.5;
    //設(shè)置圓角
    self.layer.cornerRadius = self.radius;
    self.layer.masksToBounds = YES;
}

2.平移控件

  • 在初始化方法中,給控件添加平移手勢(shì),實(shí)現(xiàn)方法
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    [self addGestureRecognizer:pan];
  • 在平移手勢(shì)的方法中,獲取當(dāng)前的偏移點(diǎn)來(lái)移動(dòng)控件
 //無(wú)法通過(guò)設(shè)置transform方法來(lái)獲得移動(dòng)中控件的frame位置的變化
    CGPoint transPoint = [pan translationInView:self];
    //平移控件
    self.transform = CGAffineTransformTranslate(self.transform, transPoint.x, transPoint.y);
    [pan setTranslation:CGPointZero inView:self];
    //利用center來(lái)改變控件的位置
    //獲取偏移點(diǎn)
    CGPoint transPoint = [pan translationInView:self];
    //平移控件
    CGPoint center = self.center;
    center.x += transPoint.x;
    center.y += transPoint.y;
    self.center = center;
    //復(fù)原
    [pan setTranslation:CGPointZero inView:self];

3.終點(diǎn)的view

  • 添加一個(gè)view在起始位置處.平移手勢(shì)方法調(diào)用頻繁,所以選擇在初始化方法中添加
    //添加小圓
    UIView *smallRadius = [[UIView alloc] initWithFrame:self.bounds];
    smallRadius.layer.cornerRadius = self.radius;
    smallRadius.center = self.center;
    smallRadius.backgroundColor = [UIColor redColor];
//    [self.superview addSubview:smallRadius];此方法是將子控件添加到父控件上,并且讓其在最上面顯示
    //將添加的view添加到父控件上
    [self.superview insertSubview:smallRadius belowSubview:self];
  • 自定義一個(gè)形變系數(shù),通過(guò)兩圓的圓心距,獲得起始圓的形變尺寸
//獲得2圓心距離
-(CGFloat) distanceWithSmallView:(UIView *) smallView withBigView:(UIView *) bigView
{
    CGFloat distanceX = bigView.center.x - smallView.center.x;
    CGFloat distanceY = bigView.center.y - smallView.center.y;
    return sqrt(distanceX * distanceX + distanceY * distanceY);
}
    //獲取小圓的半徑
    CGFloat radius = self.radius - space;
    //修改小圓的尺寸
    self.smallView.bounds = CGRectMake(0, 0, radius * 2, radius * 2);
    self.smallView.layer.cornerRadius = radius;

4.不規(guī)則矩形的創(chuàng)建

  • 通過(guò)形狀圖層,將不規(guī)則的矩形渲染到視圖
  • 創(chuàng)建貝塞爾曲線
-(UIBezierPath *) beziserWithSmallView:(UIView *) smallView withBigView:(UIView *)bigView
{
    //小 圓
    CGPoint small = smallView.center;
    CGFloat r = smallView.bounds.size.width * 0.5;
    //大 圓
    CGPoint big = bigView.center;
    CGFloat R = bigView.bounds.size.width * 0.5;    
    CGFloat distance = [self distanceWithSmallView:smallView withBigView:bigView];
    //兩控件x,y軸上的偏移量
    CGFloat spaceX = big.x - small.x;
    CGFloat spaceY = big.y - small.y;
    //獲取偏移角度
    CGFloat sinθ = spaceX / distance;
    CGFloat cosθ = spaceY / distance;
    //路徑點(diǎn)
    CGPoint pointA = CGPointMake(small.x - r * cosθ, small.y + r * sinθ);
    CGPoint pointB = CGPointMake(small.x + r * cosθ, small.y - r * sinθ);
    CGPoint pointC = CGPointMake(big.x + R * cosθ, big.y - R * sinθ);
    CGPoint pointd = CGPointMake(big.x - R * cosθ, big.y + R * sinθ);
    //曲線控制點(diǎn)
    CGPoint ctlOne = CGPointMake(pointA.x + distance * 0.5 * sinθ, pointA.y + distance * 0.5 * cosθ);
    CGPoint ctltwo = CGPointMake(pointB.x + distance * 0.5 * sinθ, pointB.y + distance * 0.5 * cosθ);
    [self.path moveToPoint:pointA];
    [self.path addLineToPoint:pointB];
    //曲線控制點(diǎn)
    [self.path addQuadCurveToPoint:pointC controlPoint:ctlOne];
    [self.path addLineToPoint:pointd];
    //曲線控制點(diǎn)
    [self.path addQuadCurveToPoint:pointA controlPoint:ctltwo];
    return self.path;
}
  • 聲明一個(gè)CAShapeLayer屬性,并且懶加載
-(CAShapeLayer *)shapeLayer
{
    if (!_shapeLayer) {
        CAShapeLayer *shapLayer = [CAShapeLayer layer];
        shapLayer.fillColor = [UIColor redColor].CGColor;
        //將形狀圖層渲染到主視圖
        [self.superview.layer addSublayer:shapLayer];
        _shapeLayer = shapLayer;
    }
    return _shapeLayer;
}

動(dòng)畫(huà)實(shí)現(xiàn)

  • 吸附效果
    if (distance >= dkSpace) { //超出范圍,將起始view和形狀圖層隱藏
        self.smallView.hidden = YES;
//        self.shapeLayer.hidden = YES;//隱藏?zé)o法達(dá)到吸附效果
        [self.shapeLayer removeFromSuperlayer];
    }else if (distance < dkSpace && !self.smallView.hidden){ //只有當(dāng)控件滿足范圍條件,并且起始view沒(méi)有隱藏的條件下,才實(shí)現(xiàn)該效果
        //通過(guò)貝塞爾創(chuàng)建不規(guī)則曲線
        self.shapeLayer.path = [self beziserWithSmallView:self.smallView withBigView:self].CGPath;
    }
  • 回彈效果
        if (distance  < dkSpace && !self.smallView.hidden) {//沒(méi)有滿足要求
            //返回起始點(diǎn)
            [UIView animateWithDuration:0.3 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:0.3 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                //返回起始點(diǎn)
                self.frame = self.smallView.frame ;
                [self.shapeLayer removeFromSuperlayer];
            } completion:^(BOOL finished) {
                self.smallView.hidden = NO;
            }];
  • 結(jié)尾動(dòng)畫(huà)效果
            //實(shí)現(xiàn)動(dòng)畫(huà)
            UIImageView *ani = [[UIImageView alloc]initWithFrame:self.bounds];
            ani.animationImages = self.icons;
            ani.animationRepeatCount = 1;
            ani.animationDuration = 1;
            [self addSubview:ani];
            //開(kāi)始動(dòng)畫(huà)
            [ani startAnimating];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.9 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self removeFromSuperview];
            });

注意

  • 應(yīng)為我們是在storyboard中拖得控件,所以默認(rèn)是會(huì)將Autoresizing轉(zhuǎn)自動(dòng)布局,需要利用代碼來(lái)設(shè)置取消
 self.view.translatesAutoresizingMaskIntoConstraints = NO;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岖瑰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌婚度,老刑警劉巖漆枚,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晋辆,死亡現(xiàn)場(chǎng)離奇詭異摇予,居然都是意外死亡配乱,警方通過(guò)查閱死者的電腦和手機(jī)按脚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)于毙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人辅搬,你說(shuō)我怎么就攤上這事唯沮〔焙担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵介蛉,是天一觀的道長(zhǎng)萌庆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)币旧,這世上最難降的妖魔是什么践险? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮吹菱,結(jié)果婚禮上巍虫,老公的妹妹穿的比我還像新娘。我一直安慰自己鳍刷,他們只是感情好占遥,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著输瓜,像睡著了一般瓦胎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尤揣,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天搔啊,我揣著相機(jī)與錄音,去河邊找鬼北戏。 笑死负芋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的最欠。 我是一名探鬼主播示罗,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼芝硬!你這毒婦竟也來(lái)了蚜点?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拌阴,失蹤者是張志新(化名)和其女友劉穎绍绘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體迟赃,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陪拘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纤壁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片左刽。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酌媒,靈堂內(nèi)的尸體忽然破棺而出欠痴,到底是詐尸還是另有隱情迄靠,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布喇辽,位于F島的核電站掌挚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏菩咨。R本人自食惡果不足惜吠式,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抽米。 院中可真熱鬧特占,春花似錦、人聲如沸云茸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查辩。三九已至,卻和暖如春网持,著一層夾襖步出監(jiān)牢的瞬間宜岛,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工功舀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萍倡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓辟汰,卻偏偏與公主長(zhǎng)得像列敲,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帖汞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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

  • 整體思路: 手指移動(dòng),按鈕跟著移動(dòng).按鈕跟著手指移動(dòng).移動(dòng)時(shí)底部有一個(gè)圓, 根據(jù)上面的大圓按鈕拖動(dòng)的距離,小圓的半...
    翻滾的企鵝閱讀 683評(píng)論 0 0
  • Core Animation Core Animation戴而,中文翻譯為核心動(dòng)畫(huà),它是一組非常強(qiáng)大的動(dòng)畫(huà)處理API翩蘸,...
    45b645c5912e閱讀 3,016評(píng)論 0 21
  • 制作步驟 1.自定義按鈕控件 設(shè)置背景顏色所意,設(shè)置layer的cornerRadius屬性,添加手勢(shì),重寫(xiě)setHi...
    沖破繭縛閱讀 1,335評(píng)論 1 7
  • 效果:拖動(dòng)信息提示數(shù)目按鈕,感覺(jué)像是在拉伸按鈕催首,當(dāng)拖動(dòng)到一定范圍扶踊,按鈕(小圓被抽出),松開(kāi)手小圓會(huì)爆炸郎任。如果抽出小...
    翻這個(gè)墻閱讀 358評(píng)論 0 0
  • 先從一段語(yǔ)錄展開(kāi)吧秧耗。“孤獨(dú)舶治,在中國(guó)字典里解釋?zhuān)率峭跽叻志?dú)是獨(dú)一無(wú)二车猬。也就是獨(dú)一無(wú)二的王者。他不需要接受任何人的認(rèn)...
    風(fēng)吹胡楊閱讀 1,221評(píng)論 0 3