PYScrollToolBarView(解決了很多手勢沖突)

scrollToolBarView演示.gif

OC: 工具類下載
pod 'PYToolBarScrollView'
swift:工具下載
pod 'PYToolBarScrollView_Swift'

一音婶、簡介

這個工具寫了很久贾富,一直不滿意,換了n種方法,最后毛瑟頓開喘先,用最平常的知識解決了問題回梧。雖然很簡單,但很巧妙浑娜。

  1. 適用結(jié)構(gòu):
    1. 頂部有一個topView
    2. 中間有個選項欄(toolBarView)
    3. 底部有scrollVIew的集合(UITableView,UICollectionView)
  2. 效果:
    1. 隨著底部的scrollView的滾動式散,topView與toolBarView也跟著上下滾動筋遭。
    2. toolBarView的到頂部的時候懸停
  3. 主要解決的問題:
    1. 解決了根據(jù)底部scrollView的不同contentOffset設(shè)置topView與toolBarView的高度問題
    2. 解決了中間toolBar懸停的問題
    3. 解決了底部scrollView左右滑動的問題

二、 知識點

  1. scrollView的一些知識暴拄,看這里
  2. 關(guān)于toolBarView的封裝漓滔,看這里
  3. CoreGraphics的知識,看這里

三乖篷、工具結(jié)構(gòu)

整體由最低層的ScrollView响驴、topViewmidToolBarView撕蔼、bottomScrollView豁鲤、還有bottomScrollViews組成
1. 主要的包含關(guān)系

  1. 最底層scrollVIew
    1.在他的上面有topView,midToolBarView鲸沮,bottomScrollView琳骡,bottomScrollViewArray
    1. 這樣的話就可以做到讓bottomViews,midToolBarView讼溺,topView日熬,一起上下滾動,只修改最低層的scrollView的contentOffset就可以了
  2. 頂部的topView
    為了擴展性肾胯,這個頂部的topView是由外部傳進(jìn)來
  3. 中間的toolBarView
    1. 這個是選項欄,也就是點擊相應(yīng)的按鈕耘纱,底部的BottomScrollView就會相應(yīng)相應(yīng)的界面
    2. toolBarView的點擊事件有傳出到外部
    3. toolBarView的titleArray應(yīng)該與BottomScrollView中的bottomScrollViewArray數(shù)目一致
    4. 點擊滑動到相應(yīng)的ScrollView界面
    5. 與下部的BottomScrollView滑動不會產(chǎn)生沖突
  4. 底部的BottomScrollView
    1. 主要是承接bottomScrollViewArray敬肚,讓他們依次排列,并且可以左右滾動
    2. 設(shè)置了分頁束析,每次到新的頁面都會向外發(fā)送index和ScrollView消息
    3. 對數(shù)組長度進(jìn)行了判斷艳馒,避免了數(shù)組越界造成的崩潰
  5. bottomScrollViewArray
    1. 這個是外部傳入的scrollView 的數(shù)組
    2. 內(nèi)部監(jiān)聽了bottomScrollViewArray元素的contentOffset,對self.contentOffset進(jìn)行設(shè)置员寇,達(dá)到聯(lián)動效果

四弄慰、遇到的問題

1. 當(dāng)?shù)撞坑卸鄠€scrollView或者多個view的時候,解決底部scrollView的contentOffset不一致造成的self.contentOffset的滑動突兀的問題
造成這個問題的根本原因是:

  1. 我在外部傳入BottomScrollViewArray的時候會先判斷其是否為scrollView蝶锋,如果是scrollView陆爽,那么監(jiān)聽了scrollView的contentOffset,并根據(jù)scrollView的contentOffset扳缕,改變self.contentOffset
  2. 在監(jiān)聽的會調(diào)函數(shù)中别威,根據(jù)監(jiān)聽到的ScrollView的滾動的contentOffset改變self.contentOffset
  3. 如果驴剔,bottomScrollViewArray中有A省古、B兩個scrollView做下面操作
    1. A滾動30的距離(這時候self.contentOffset.y跟隨A變成了30)
    2. 現(xiàn)在切換到了B丧失,這時候就會出現(xiàn)問題
    3. 因為B的contentOffset.y為0豺妓,而self.contentOffset為30,當(dāng)你在滑動B的時候布讹,B的contentOffset發(fā)生改變,那么將對self.contentOffset重新賦值炒事,這時候,B的contentOffset.y為0挠乳,而self.contentOffset.y為30,則self.contentOffset會直接變成0

解決方案:

  1. 添加了一個OffsetY變量权薯。
    在將要切換的底部的scrollView的時候?qū)與B進(jìn)行contentOffset.y差值計算。
    在B滑動的時候把差值也算入到self.contentOffset中睡扬。
    在滑動到頂部盟蚣,或者底部的時候卖怜,對offsetY進(jìn)行清零
    但是還是有缺陷屎开,比如A的contentOffset.y 為0马靠,而self.contentOffset.y已經(jīng)到最大,那么切換到A甩鳄,向下拉,也會有self直接掉下來的突兀感

代碼:

 ///布局bottomScrollView的subView (把subView添加到了bottomScrollViewView里面)
    private func setupBottomScrollViewSubView(_ contentOffsetY: CGFloat) {
        for index: NSInteger in 0 ..< self.bottomViewArray.count {
            //布局subview
            let view: UIView = self.bottomViewArray[index]
            self.bottomScrollView.addSubview(view)
            view.frame = CGRect(x: kToolBarScrollViewW * CGFloat(index), y:0, width: kToolBarScrollViewW, height: kBottomScrollViewH + contentOffsetY)
            //如果要是是ScrollView的子類那么監(jiān)聽contentOffset
            if view is UIScrollView {
                let scrollView: UIScrollView = view as! UIScrollView
                scrollView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
            }
        }
    }

 ///通知的方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "contentOffset" {
//            print(change?[NSKeyValueChangeKey.newKey] ?? "----- 沒有紙")
            let scrollView: UIScrollView = object as! UIScrollView
            //獲取偏移量
            let newValue: CGPoint = change?[NSKeyValueChangeKey.newKey] as! CGPoint
            self.newValue = newValue;
            //改變scrollView偏移的位置
            if scrollView.contentOffset.y <= 0{
                if newValue.y < 0 {
                    self.offset = 0
                }
                self.contentOffset = CGPoint(x: 0, y: 0)
            }
            if scrollView.contentOffset.y >= self.kTopViewH {
                if newValue.y > self.kTopViewH {
                    self.offset = 0
                }  
                self.contentOffset = CGPoint(x: 0, y: self.kTopViewH)
            }
//            let isScrollBottom = Int(scrollView.contentSize.height - self.contentOffset.y) <= Int(scrollView.frame.size.height);
            if scrollView.contentSize.height <= scrollView.frame.size.height + kTopViewH {   
                let insertY = scrollView.frame.size.height + kTopViewH - scrollView.contentSize.height   
                scrollView.contentInset = UIEdgeInsetsMake(0, 0, insertY, 0)
            }else{
                scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
            }
            self.contentOffset = CGPoint(x: 0, y: newValue.y + self.offset)
        }
    }

2. 當(dāng)前顯示的scrollView的contentSize滑動不到頂部档泽,底部的scrollView就會顯示不全
解決方法:
在滾動的時候判斷,當(dāng)前的scrollView的滑動范圍馆匿,是否足以讓self滑動到頂部

 if scrollView.contentSize.height <= scrollView.frame.size.height + kTopViewH {
                
                let insertY = scrollView.frame.size.height + kTopViewH - scrollView.contentSize.height
                
                scrollView.contentInset = UIEdgeInsetsMake(0, 0, insertY, 0)
            }else{
                scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
            }
            
            self.contentOffset = CGPoint(x: 0, y: newValue.y + self.offset)
        }

更新:2017.11.15

1. PYMidView的擴展

  1. 對中間的toolBarView的擴展性燥滑,進(jìn)行了修復(fù)渐北。添加了一個PYMidView(繼承自UIView)突倍,他有個代理屬性盆昙,var delegate: PYToolBarViewProtocol?要求實現(xiàn)一個方法,返回對應(yīng)的toolBarView,
  2. 事實上淡喜,你只要繼承PYMidView,然后在里面布局子控件炼团,并且,把代理屬性設(shè)置成自己瘟芝,實現(xiàn)代理方法,就可以完美適應(yīng)任何產(chǎn)品需求锌俱。

*代碼

import UIKit
class PYMidView: UIView {
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    var delegate: PYToolBarViewProtocol?
    private var isFirstSetToolBarUI: Bool = true
    
    override func layoutSubviews() {
        if isFirstSetToolBarUI {
            self.delegate?.registerToolBarView().displayUI()
            layoutIfNeeded()
            isFirstSetToolBarUI = false
        }
    }
}

更新:2018.1.5

進(jìn)行了重構(gòu)敌呈,具體思路差不多贸宏,只是提高了兼容性磕洪,與遺留bug的修復(fù)。
下一步析显,準(zhǔn)備兼容web 滑動的監(jiān)聽。具體看代碼:

OC: 工具類下載
pod 'PYToolBarScrollView'
swift:工具下載
pod 'PYToolBarScrollView_Swift'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谷异,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子歹嘹,更是在濱河造成了極大的恐慌,老刑警劉巖荞下,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件史飞,死亡現(xiàn)場離奇詭異,居然都是意外死亡构资,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門迹淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來河绽,“玉大人唉窃,你說我怎么就攤上這事耙饰∥品荩” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵蔓涧,是天一觀的道長。 經(jīng)常有香客問我元暴,道長,這世上最難降的妖魔是什么茉盏? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮歼狼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羽峰。我一直安慰自己,他們只是感情好梅屉,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坯汤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惰聂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天搓幌,我揣著相機與錄音迅箩,去河邊找鬼溉愁。 笑死饲趋,一個胖子當(dāng)著我的面吹牛拐揭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播堂污,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼息楔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扒披,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎愿险,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辆亏,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡鳖目,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年扮叨,在試婚紗的時候發(fā)現(xiàn)自己被綠了领迈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狸捅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尘喝,到底是詐尸還是另有隱情,我是刑警寧澤朽褪,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站缔赠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橡淑。R本人自食惡果不足惜咆爽,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一置森、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧符糊,春花似錦、人聲如沸男娄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至尸折,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間实夹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工亮航, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缴淋。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像宴猾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仇哆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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