Xamarin - UITableView 長按拖動Cell

  1. UITableView 添加長按事件
    LongPress = new UILongPressGestureRecognizer(new Action(() => { Cell_OnMove(); }));
    tableView.AddGestureRecognizer(LongPress);
    其中Cell_OnMove中代碼如下:
    switch (LongPress.State)
    {
    case UIGestureRecognizerState.Began:
    GestureBegan();
    break;
    case UIGestureRecognizerState.Changed:
    //ProcessScroll();
    break;
    case UIGestureRecognizerState.Ended:
    GestureEnded();
    break;
    }

  2. 各個(gè)長按狀態(tài)的響應(yīng)事件
    2.1 長按手勢開始
    /// <summary>
    /// 長按手勢開始
    /// </summary>
    void GestureBegan()
    {
    // 得到當(dāng)前長按的點(diǎn)相對于長按手勢載體的位置
    CGPoint location = LongPress.LocationInView(LongPress.View);
    // 根據(jù)位置得到IndexPath
    NSIndexPath indexPath = TableView.IndexPathForRowAtPoint(location);
    // 根據(jù)IndexPath得到Cell
    var cell = TableView.CellAt(indexPath) as OptionEditCell;
    // 記錄長按開始的位置
    sourceIndex = NSIndexPath.FromRowSection(indexPath.Row, 0);
    // 得到cell的移動截圖
    snapShotView = GetMoveCellImage(cell);
    // 開啟邊緣滑動
    StartScroll();
    CGPoint center = cell.Center;
    snapShotView.Center = center;
    snapShotView.Alpha = 0;
    TableView.AddSubview(snapShotView);
    UIView.Animate(0.1, new Action(() =>
    {
    center.Y = location.Y;
    snapShotView.Center = center;
    snapShotView.Transform = CGAffineTransform.MakeScale(1f, 1f);
    snapShotView.Alpha = 1f;
    cell.Alpha = 0;
    }));
    }
    2.2 長按手勢變化
    /// <summary>
    /// 長按手勢變化
    /// </summary>
    void GestureChanged()
    {
    // 得到當(dāng)前長按的點(diǎn)相對于長按手勢載體的位置
    CGPoint location = LongPress.LocationInView(LongPress.View);

         // 移動位置超出上邊界則等于上邊界
         if (location.Y <= 0) location.Y = 0;
         // 移動位置超出下邊界則等于下邊界
         if (location.Y >= TableView.ContentSize.Height - 1) location.Y = TableView.ContentSize.Height - 1;
    
         NSIndexPath indexPath = TableView.IndexPathForRowAtPoint(location);
         var cell = TableView.CellAt(indexPath) as OptionEditCell;
         if (cell == null) return;
         CGPoint cen = snapShotView.Center;
         cen.Y = location.Y;
         snapShotView.Center = cen;
         cell.Alpha = 0;
         if (indexPath != null && !indexPath.Equals(sourceIndex))
         {
             // 移動行辙芍,是界面有滑動填充的效果
             Source_OnItemMoved(sourceIndex.Row, indexPath.Row);
             // 記錄cell的新位置
             sourceIndex = indexPath;
         }
     }
    

2.3 長按手勢結(jié)束
/// <summary>
/// 長按手勢結(jié)束
/// </summary>
void GestureEnded()
{
UIView.Animate(0.15, new Action(() =>
{
// 此處使用sourceIndex费坊,也就是Changed中變化后的位置茅逮,如果重新取值有可能取到下一個(gè)cell,導(dǎo)致移動的cell沒有恢復(fù)alpha值
var sourceCell = TableView.CellAt(sourceIndex) as OptionEditCell;
sourceCell.Alpha = 1;
snapShotView.Center = sourceCell.Center;
snapShotView.Transform = CGAffineTransform.MakeIdentity();
snapShotView.Alpha = 0;

            // 停止scrollTimer
            scrollTimer.RemoveFromRunLoop(NSRunLoop.Main, NSRunLoopMode.Common);
        }), new Action(() =>
        {
            // 移除snapShotView
            snapShotView.RemoveFromSuperview();
            snapShotView = null;
        }));
    }
  1. 開啟滾動事件
    void StartScroll()
    {
    scrollTimer = CADisplayLink.Create(ProcessScroll);
    scrollTimer.AddToRunLoop(NSRunLoop.Main, NSRunLoopMode.Common);
    }

  2. 滾動事件
    /// <summary>
    /// 邊緣滾動事件
    /// </summary>
    void ProcessScroll()
    {
    // 觸發(fā)長按變化事件
    GestureChanged();

         // 設(shè)置向上移動時(shí)培己,TableView開始滑動的邊界
         nfloat minOffsetY = tableView.ContentOffset.Y + edgeScrollRange;
         // 設(shè)置向下移動時(shí),TableView開始滑動的邊界
         nfloat maxOffsetY = tableView.ContentOffset.Y + tableView.Frame.Height - edgeScrollRange;
         // 得到截圖的當(dāng)前位置
         CGPoint touchPoint = snapShotView.Center;
    
         // 截圖位置達(dá)到向上的滾動條件实苞,但是沒有可以滾動的內(nèi)容
         if (touchPoint.Y < edgeScrollRange && tableView.ContentOffset.Y <= 0) return;
         // 截圖位置滿足向下的滾動條件剪廉,但是沒有可以滾動的內(nèi)容
         if ((touchPoint.Y > tableView.ContentSize.Height - edgeScrollRange) &&
            (tableView.ContentOffset.Y >= tableView.ContentSize.Height - tableView.Frame.Height)) return;
    
         nfloat maxMoveDistance = 10f;
         if (touchPoint.Y < minOffsetY)
         {
             nfloat moveDistance = (minOffsetY - touchPoint.Y) / edgeScrollRange * maxMoveDistance;
             // 確保停止后,TableView頂部不出現(xiàn)空白
             if (tableView.ContentOffset.Y - moveDistance <= 0)
                 moveDistance = tableView.ContentOffset.Y;
             tableView.SetContentOffset(new CGPoint(tableView.ContentOffset.X, tableView.ContentOffset.Y - moveDistance), false);
             snapShotView.Center = new CGPoint(snapShotView.Center.X, snapShotView.Center.Y - moveDistance);
         }
         else if(touchPoint.Y > maxOffsetY)
         {
             nfloat moveDistance = (touchPoint.Y - maxOffsetY) / edgeScrollRange * maxMoveDistance;
             // 確保停止后朴肺,TableView底部不出現(xiàn)空白
             if (tableView.ContentOffset.Y + moveDistance >= tableView.ContentSize.Height - tableView.Frame.Height)
                 moveDistance = tableView.ContentSize.Height - tableView.Frame.Height - tableView.ContentOffset.Y;
             tableView.SetContentOffset(new CGPoint(tableView.ContentOffset.X, tableView.ContentOffset.Y + moveDistance), false);
             snapShotView.Center = new CGPoint(snapShotView.Center.X, snapShotView.Center.Y + moveDistance);
         }
     }
    

文章根據(jù) http://www.reibang.com/p/ce382f9bc794 這里的思路來寫窖剑,整體思路一樣,但是實(shí)現(xiàn)上有些不一樣的地方戈稿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末西土,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鞍盗,更是在濱河造成了極大的恐慌需了,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件般甲,死亡現(xiàn)場離奇詭異肋乍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)敷存,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進(jìn)店門墓造,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事觅闽〉酃停” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵谱煤,是天一觀的道長摊求。 經(jīng)常有香客問我,道長刘离,這世上最難降的妖魔是什么室叉? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮硫惕,結(jié)果婚禮上茧痕,老公的妹妹穿的比我還像新娘。我一直安慰自己恼除,他們只是感情好踪旷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豁辉,像睡著了一般令野。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徽级,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天气破,我揣著相機(jī)與錄音,去河邊找鬼餐抢。 笑死现使,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的旷痕。 我是一名探鬼主播碳锈,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欺抗!你這毒婦竟也來了售碳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤绞呈,失蹤者是張志新(化名)和其女友劉穎团滥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體报强,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灸姊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秉溉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片力惯。...
    茶點(diǎn)故事閱讀 39,703評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碗誉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出父晶,到底是詐尸還是另有隱情哮缺,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布甲喝,位于F島的核電站尝苇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏埠胖。R本人自食惡果不足惜糠溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望直撤。 院中可真熱鬧非竿,春花似錦、人聲如沸谋竖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蓖乘。三九已至锤悄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嘉抒,已是汗流浹背零聚。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留众眨,地道東北人握牧。 一個(gè)月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓容诬,卻偏偏與公主長得像娩梨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子览徒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評論 2 353

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