iOS_UI進(jìn)階【拖拽排序】的實(shí)現(xiàn)

導(dǎo)讀

拖拽排序是新聞?lì)惖腁pp可以說(shuō)是必有的交互設(shè)計(jì)和敬,如今日頭條,網(wǎng)易新聞等采桃。拖拽排序是一個(gè)交互體驗(yàn)非常好的設(shè)計(jì)懒熙,簡(jiǎn)單,方便普办。

今日頭條的拖拽排序界面
今日頭條的拖拽排序界面.png
我實(shí)現(xiàn)的長(zhǎng)按拖拽排序效果
長(zhǎng)按拖拽排序.gif
實(shí)現(xiàn)方案

1.給CollectionViewCell添加一個(gè)長(zhǎng)按手勢(shì)肢娘,通過(guò)代理把手勢(shì)傳遞到collectionView所在的控制器中。
- (void)awakeFromNib{
self.layer.cornerRadius = 3;
self.layer.masksToBounds = YES;
//給每個(gè)cell添加一個(gè)長(zhǎng)按手勢(shì)
UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
longPress.delegate = self;
[self addGestureRecognizer:longPress];
}

- (void)longPress:(UILongPressGestureRecognizer *)longPress{
    if (self.delegate && [self.delegate respondsToSelector:@selector(longPress:)]) {
        [self.delegate longPress:longPress];
    }
}

2.開(kāi)始長(zhǎng)按時(shí)對(duì)cell進(jìn)行截圖舆驶,并隱藏cell橱健。

- (void)longPress:(UILongPressGestureRecognizer *)longPress{
    //記錄上一次手勢(shì)的位置
    static CGPoint startPoint;
    //觸發(fā)長(zhǎng)按手勢(shì)的cell
    MovingCell * cell = (MovingCell *)longPress.view;
    //開(kāi)始長(zhǎng)按
    if (longPress.state == UIGestureRecognizerStateBegan) {
        [self shakeAllCell];
        //獲取cell的截圖
        _snapshotView  = [cell snapshotViewAfterScreenUpdates:YES];
        _snapshotView.center = cell.center;
        [_collectionView addSubview:_snapshotView];
        _indexPath= [_collectionView indexPathForCell:cell];
        _originalCell = cell;
        _originalCell.hidden = YES;
        startPoint = [longPress locationInView:_collectionView];
    }

3、在手勢(shì)移動(dòng)的時(shí)候沙廉,移動(dòng)截圖視圖拘荡,用遍歷的方法求出截圖移動(dòng)到哪個(gè)cell的位置,再調(diào)用系統(tǒng)的api交換這個(gè)cell和隱藏cell的位置撬陵,并且數(shù)據(jù)源中的數(shù)據(jù)也需要調(diào)整順序

    //手勢(shì)移動(dòng)的時(shí)候
    else if (longPress.state == UIGestureRecognizerStateChanged){
    CGFloat tranX = [longPress locationOfTouch:0 inView:_collectionView].x - startPoint.x;
    CGFloat tranY = [longPress locationOfTouch:0 inView:_collectionView].y - startPoint.y;
    //設(shè)置截圖視圖位置
    _snapshotView.center = CGPointApplyAffineTransform(_snapshotView.center, CGAffineTransformMakeTranslation(tranX, tranY));
    startPoint = [longPress locationOfTouch:0 inView:_collectionView];
    //計(jì)算截圖視圖和哪個(gè)cell相交
    for (UICollectionViewCell *cell in [_collectionView visibleCells]) {
        //跳過(guò)隱藏的cell
        if ([_collectionView indexPathForCell:cell] == _indexPath) {
            continue;
        }
        //計(jì)算中心距
        CGFloat space = sqrtf(pow(_snapshotView.center.x - cell.center.x, 2) + powf(_snapshotView.center.y - cell.center.y, 2));

        //如果相交一半且兩個(gè)視圖Y的絕對(duì)值小于高度的一半就移動(dòng)
        if (space <= _snapshotView.bounds.size.width * 0.5 && (fabs(_snapshotView.center.y - cell.center.y) <= _snapshotView.bounds.size.height * 0.5)) {
            _nextIndexPath = [_collectionView indexPathForCell:cell];
            if (_nextIndexPath.item > _indexPath.item) {
                for (NSUInteger i = _indexPath.item; i < _nextIndexPath.item ; i ++) {
                    [self.array exchangeObjectAtIndex:i withObjectAtIndex:i + 1];
                }
            }else{
                for (NSUInteger i = _indexPath.item; i > _nextIndexPath.item ; i --) {
                    [self.array exchangeObjectAtIndex:i withObjectAtIndex:i - 1];
                }
            }
            //移動(dòng)
            [_collectionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath];
            //設(shè)置移動(dòng)后的起始indexPath
            _indexPath = _nextIndexPath;
            break;
        }
    }

4.手勢(shì)停止時(shí)珊皿,移除截圖的view网缝,顯示隱藏cell

//手勢(shì)停止時(shí)
}else if(longPress.state == UIGestureRecognizerStateEnded){
    [self stopShake];
    [_snapshotView removeFromSuperview];
    _originalCell.hidden = NO;
}
其他

代碼還可以進(jìn)一步封裝,寫(xiě)一個(gè)數(shù)據(jù)管理類(lèi)dataTool蟋定,dataTool作為collectionView的數(shù)據(jù)源粉臊,所有的數(shù)據(jù)源方法都寫(xiě)到dataTool類(lèi)中。手勢(shì)的代理方法也在里面實(shí)現(xiàn)驶兜,這樣控制器會(huì)簡(jiǎn)潔很多维费,控制器就不需要關(guān)注拖拽排序的具體邏輯了。大家有空可以自己寫(xiě)寫(xiě)看促王,也許你們有更好的處理方案犀盟,可以評(píng)論交流一下。
github地址:https://github.com/HelloYeah/DraggingSort

提示

如果你們是從iOS9開(kāi)始適配的話(huà)蝇狼,那么可以用系統(tǒng)的Api阅畴,非常簡(jiǎn)單好用

//是否允許拖拽
 - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
 /**
  *   從sourceIndexPath 拖拽至destinationIndexPath,在這個(gè)代理方法里修改數(shù)據(jù)源即可迅耘。
  *   exchangeObjectAtIndex:sourceIndexPath.item withObjectAtIndex: destinationIndexPath.item
  */
 - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath NS_AVAILABLE_IOS(9_0);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贱枣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子颤专,更是在濱河造成了極大的恐慌纽哥,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栖秕,死亡現(xiàn)場(chǎng)離奇詭異春塌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)簇捍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)只壳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人暑塑,你說(shuō)我怎么就攤上這事吼句。” “怎么了事格?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵惕艳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我驹愚,道長(zhǎng)远搪,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任么鹤,我火速辦了婚禮终娃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己棠耕,他們只是感情好余佛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著窍荧,像睡著了一般辉巡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蕊退,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天郊楣,我揣著相機(jī)與錄音,去河邊找鬼瓤荔。 笑死净蚤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的输硝。 我是一名探鬼主播今瀑,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼点把!你這毒婦竟也來(lái)了橘荠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郎逃,失蹤者是張志新(化名)和其女友劉穎哥童,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體褒翰,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贮懈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了影暴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片错邦。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖型宙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伦吠,我是刑警寧澤妆兑,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站毛仪,受9級(jí)特大地震影響搁嗓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箱靴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一腺逛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衡怀,春花似錦棍矛、人聲如沸安疗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)荐类。三九已至,卻和暖如春茁帽,著一層夾襖步出監(jiān)牢的瞬間玉罐,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工潘拨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吊输,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓铁追,卻偏偏與公主長(zhǎng)得像季蚂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脂信,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)癣蟋、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,105評(píng)論 4 62
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議狰闪。它實(shí)...
    香橙柚子閱讀 23,869評(píng)論 8 183
  • 本章參與人:Yang疯搅,清姐,小多埋泵,翔仔 “好幔欧,那就去看看吧±錾”Mr.Yang說(shuō)礁蔗,“所以我們還是要修船⊙闵纾” …… “...
    SGcat閱讀 434評(píng)論 0 2
  • 01 “瑩瑩浴井,秦宇離開(kāi)我了,他不要我……我不想活了”電話(huà)里傳來(lái)谷雪的哭聲霉撵,很沙啞磺浙。 “谷雪,你千萬(wàn)不要做傻事徒坡,我馬...
    三蛋蝦扯蛋閱讀 2,967評(píng)論 105 83