可拖拽的小窗口,最好用?

一、前言

  • 1、寫了10多天的小程序代碼,有興趣的可以看我這篇小程序官方文檔-小程序版【持續更新】,被坑得有點暈,突然想換換口味,寫點iOS的,看群上有人提過這個拖拽view的功能,應該挺多人需要的,那就造一個分享吧。

  • 2、公司有自己的一個直播項目,看其他直播app都有小屏幕可拖拽播放的view(如下圖),雖然還沒有這個需求,早點準備好。

截圖來自某牙直播
  • 3、而且很久沒分享了,像往常一樣,封裝輪子的過程都會詳細介紹,分享更多的都是封裝的思想。

  • 4、來看看效果圖先吧:

    演示效果圖,還可以吧

二、功能分析(針對所有控件)

  • 1、可拖拽。最基本的功能,拖出父容器松手后可復位,可關閉。

  • 2、拖拽不遮蓋。同級層次的控件,如果拖拽過程中出現重疊,會顯示在最上層。

  • 3、可吸附邊界。吸附這點參考蘋果的AssistiveTouch,只能在屏幕的左邊或者右邊,可關閉。

  • 4、彈簧效果。如果超出屏幕,會有彈簧效果,這點參考scrollView 的 bounces 效果,可關閉。

  • 5、支持xib、storyboard 參數設置。很多控件都是在xib或storyboard 中創建,此時可通過,看下圖:

支持xib、storyboard 參數設置

三、API 分析設計

  • 1、是否允許拖拽,默認關閉,支持xib、storyboard 參數設置
/**
 *  @author gitKong
 *
 *  是否允許拖拽,默認關閉(可以在XIB或SB中設置)
 */
@property (nonatomic,assign)IBInspectable BOOL fl_canDrag;
  • 2、是否需要邊界彈簧效果,默認開啟,支持xib、storyboard 參數設置
/**
 *  @author gitKong
 *
 *  是否需要邊界彈簧效果,默認開啟(可以在XIB或SB中設置)
 */
@property (nonatomic,assign)IBInspectable BOOL fl_bounces;
  • 3、是否需要吸附邊界效果,默認開啟(可以在XIB或SB中設置
/**
 *  @author gitKong
 *
 *  是否需要吸附邊界效果,默認開啟(可以在XIB或SB中設置)
 */
@property (nonatomic,assign)IBInspectable BOOL fl_isAdsorb;

四、功能實現分析

  • 1、分類或繼承實現。因為需要支持所有控件,我們都知道控件都是直接或者間接繼承 UIView ,此時可以有兩種辦法實現,繼承分類 ,此時我是用分類實現的,至于為什么呢?

    • (1)、如果我當前的view是已經繼承了另一個自定義view,而且功能很獨立,此時如果要給當前view添加拖拽功能的話,就必須融合兩個功能的代碼,這將變得很麻煩,而且會很亂。

    • (2)、如果我需要給一個按鈕添加拖拽功能,那么繼承就沒辦法實現了,因為你給這個按鈕修改了繼承,就沒了自帶的功能了。

  • 2、監聽拖拽。拖拽事件可以通過 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 方法去監聽,也可以通過添加 pan 拖拽手勢,至于為什么要用 手勢呢?

    • (1)、需要在分類中實現 touchesMoved 方法,此時如果外界也實現了這個方法,那么就很容易起沖突。
    • (2)、雖然動態修改拖拽功能開關,但 會 多次調用 touchesMoved 方法,即使關閉了拖拽功能,相對手勢實現就沒那么靈活了。
  • 3、Setter 方法里添加pan事件。一開始想到的是通過 runtime 的 Swizzle 替換掉 系統的 init 方法,進而在自己的方法里面實現 拖拽手勢添加,但后來考慮到,此時是給UIView 添加分類,而頁面上的所有控件都是UIView 的 子類,此時 init 就會調用多次,會造成頁面顯示慢;于是直接在setter方法里面判斷,當需要拖拽的時候,我才添加事件,不需要拖拽的時候移除手勢,算是一個小優化。此時還需要記錄當前控件在父容器中的 index ,這個等下就知道要用來干嘛。

  • 4、遮蓋處理。我們都知道,控件通過 addSubviews 添加到父容器中,是有順序的,后面添加的會在上層;此時如果我先添加 view1 在添加 view2,我拖拽 view1 到 view2 的時候,就會被 view2 擋住。做法如下:

    • (1)、遍歷父類view 的 subViews 數組,判斷是否與當前view重合,用系統自帶的 CGRectIntersectsRect 方法判斷。
    • (2)、在拖拽開始(UIGestureRecognizerStateBegan)的時候,用 bringSubviewToFront 將拖拽的view 移到最上層。
    • (3)、在拖拽結束(UIGestureRecognizerStateEnd)的時候,判斷此時狀態是否還重合,如果不重合,通過 insertSubview 將控件重置回原來的順序(通過上面第三點記錄的 index
  • 5、支持xib、storyboard 參數設置。這個只需要添加一個 關鍵字修飾就行 IBInspectable ,用法可以看我API 設計,這個主要作用是使view內的變量可視化,并且可以修改后馬上看到

  • 6、彈簧效果和吸附效果。這個可以使用UIView 的 動畫就可以實現,此時有一個注意點,判斷吸附到左邊還是右邊,比較的應該是絕對位置,而不是相對位置,需要加上父類的x值

if (gesR.view.fl_centerX + self.superview.fl_x > self.superview.fl_centerX) {
    [UIView animateWithDuration:0.25 animations:^{
        gesR.view.center = CGPointMake(self.superview.fl_width - self.fl_width / 2, y);
    }];
    
}
else{
    [UIView animateWithDuration:0.25 animations:^{
        gesR.view.center = CGPointMake(self.fl_width / 2, y);
    }];
}
計算小坑

五、注意點:

  • 1、如果你是使用約束來布局的話,此時可能出現當你拖拽出一定范圍后,能正常停留在當前位置;但當你此時拖拽后的位置在約束好的位置附近,就會被吸附回去,如下圖:(此時圖片是使用約束布局
使用約束布局可能會出現這種情況
  • 2、如果手勢失敗,會有斷言提示。

六、總結

  • 1、為了方便大家使用,支持cocoapod,通過 pod search FLDragView 就能搜到。如果你搜不到,先清理一下吧,執行 rm ~/Library/Caches/CocoaPods/search_index.json 執行完重新 search 就行

    cocoapod
  • 2、代碼不難實現,具體代碼就不拷貝上來了,代碼中計算相對多一點,文字分析應該比較清楚了,如果還有什么其他問題,盡管找我。

  • 3、Github地址 ,歡迎大家關注我,喜歡給個star 和 like ,你的支持是我最大的動力,會隨時更新原創文章喔!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,615評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,151評論 4 61
  • 在Android逆向分析(2) APK的打包與安裝一文中對資源編譯過程的介紹中,筆者提到了overlay(重疊包)...
    MarkZhai閱讀 11,186評論 1 15
  • 人類總是愛和自己鬧對立,用自己目前的痛苦哄騙自己的希望,又用并不屬于自己的前程,來欺騙目前的痛苦。人類的一切行為,...
    章可可閱讀 456評論 3 1
  • 二水: 展信佳。 今天學校里迎新生,第一項升國旗,想起原來我們四個人的學校升國旗的時候。噗,我每次都是站在護旗手迎...
    銘1993閱讀 373評論 0 0