iOS 給view加一個拖拽功能

前言

現(xiàn)在的直播app都具有懸浮窗功能,懸浮窗可以拖拽,并且具有回彈動畫,可以設(shè)計一個UIView的分類實現(xiàn),減少侵入性。

主要代碼及思路

思路

  • 給view添加一個pan的手勢,在gesture的狀態(tài)中進行判斷(例如邊界的回彈),最終拖拽手勢結(jié)束時,通過block把手勢回調(diào)出去。

代碼

#import "UIView+dragable.h"
#import <objc/runtime.h>

#define ScreenWidth                         [[UIScreen mainScreen] bounds].size.width
#define ScreenHeight                        [[UIScreen mainScreen] bounds].size.height

static const char *ActionHandlerPanGestureKey;

@implementation UIView (dragable)

- (void)addDragableActionWithEnd:(void (^)(CGRect endFrame))endBlock; {
    // 添加拖拽手勢
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanAction:)];
    [self addGestureRecognizer:panGestureRecognizer];
    
    // 記錄block
    objc_setAssociatedObject(self, ActionHandlerPanGestureKey, endBlock, OBJC_ASSOCIATION_COPY);
}

@end

  • 由于在uiview的分類中,所以使用了runtime關(guān)聯(lián)一下需要回調(diào)的block
- (void)handlePanAction:(UIPanGestureRecognizer *)sender {
    CGPoint point = [sender translationInView:[sender.view superview]];
    
    CGFloat senderHalfViewWidth = sender.view.frame.size.width / 2;
    CGFloat senderHalfViewHeight = sender.view.frame.size.height / 2;
    
    __block CGPoint viewCenter = CGPointMake(sender.view.center.x + point.x, sender.view.center.y + point.y);
    // 拖拽狀態(tài)結(jié)束
    if (sender.state == UIGestureRecognizerStateEnded) {
        [UIView animateWithDuration:0.4 animations:^{
            if ((sender.view.center.x + point.x - senderHalfViewWidth) <= 12) {
                viewCenter.x = senderHalfViewWidth + 12;
            }
            if ((sender.view.center.x + point.x + senderHalfViewWidth) >= (ScreenWidth - 12)) {
                viewCenter.x = ScreenWidth - senderHalfViewWidth - 12;
            }
            if ((sender.view.center.y + point.y - senderHalfViewHeight) <= 12) {
                viewCenter.y = senderHalfViewHeight + 12;
            }
            if ((sender.view.center.y + point.y + senderHalfViewHeight) >= (ScreenHeight - 12)) {
                viewCenter.y = ScreenHeight - senderHalfViewHeight - 12;
            }
            sender.view.center = viewCenter;
        } completion:^(BOOL finished) {
            void (^endBlock)(CGRect endFrame) = objc_getAssociatedObject(self, ActionHandlerPanGestureKey);
            if (endBlock) {
                endBlock(sender.view.frame);
            }
        }];
        [sender setTranslation:CGPointMake(0, 0) inView:[sender.view superview]];
    } else {
        // UIGestureRecognizerStateBegan || UIGestureRecognizerStateChanged
        viewCenter.x = sender.view.center.x + point.x;
        viewCenter.y = sender.view.center.y + point.y;
        sender.view.center = viewCenter;
        [sender setTranslation:CGPointMake(0, 0) inView:[sender.view superview]];
    }
}
  • UIGestureRecognizerState有個狀態(tài)是UIGestureRecognizerStateEnded,當(dāng)拖拽結(jié)束時,需要判斷拖拽視圖的位置是否超出屏幕邊界,如果超出邊界,需要回彈到邊界內(nèi)。
  • 回彈動畫結(jié)束后,用runtime取出關(guān)聯(lián)的block,把最終的視圖的frame回調(diào),供外部使用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,407評論 4 61
  • 在假期的最后一天大掃除時,終于把那拆得七零八散的熱水器給丟樓下垃圾桶了。但是心情還是不舍。畢竟陪我在這個城市...
    閑趣的肖小姐閱讀 315評論 0 0
  • 朋友,今天的你,過28歲了嗎?開始懷念青春了嗎? 那時候,桌子上堆滿了各科的習(xí)題,床頭貼著“戰(zhàn)勝自我”之類的座右銘...
    我是東北仁兒閱讀 520評論 0 3
  • 無味的生活總需要一個有趣的人,原諒我的膽怯、懦弱,我不想失去,也未曾奢望得到過
    密秘的密秘閱讀 299評論 0 0
  • 九月她陪我買支牙膏 與她早已不再相見 二月干癟仍能擠出 一支牙膏足夠五月有余 一生一人行至耄耋 收縮牙床零落黃牙 ...
    任一蓑閱讀 428評論 0 1

友情鏈接更多精彩內(nèi)容