【code_小馬】解決ScrollView上按鈕攔截響應的問題

我們是工程師 ——加油 !

老樣子,先上代碼解燃眉之急,具體思路解釋 見下文

/*UIScrollView高級用法:
delaysContentTouches與
canCencelContentTouches屬性*/

需求:

UIScrollView+btns。點擊btn高亮(Highlighted),滑動UIScrollView時取消高亮;

分析:

1.實現:點擊btn高亮(Highlighted),且滑動UIScrollView時保持高亮狀態,是不合理的,無法實現的。(ps還不如直接用cell或者btn的選中狀態)
2.實現:點擊btn高亮(Highlighted), 滑動UIScrollView時取消高亮狀態,是可以做到的。

按照從不同的要素去解釋原理:

一、UIScrollView原理,以時間為軸線:

從你的手指touch屏幕開始,scrollView開始一個timer,如果:

  1. 150ms內如果你的手指沒有任何動作,消息就會傳給subView。
  2. 150ms內手指有明顯的滑動(一個swipe動作),scrollView就會滾動,消息不會傳給subView。
  3. 150ms內手指沒有滑動,scrollView將消息傳給subView,但是之后手指開始滑動,scrollView傳送touchesCancelled消息給subView,然后開始滾動。

二、UIScrollView原理,以tracking屬性為軸線:

UIScrollView有一個BOOL類型的tracking屬性,用來返回用戶是否已經觸及內容并打算開始滾動,我們從這個屬性開始探究UIScrollView的工作原理:

當手指觸摸到UIScrollView內容的一瞬間,會有以下動作:

  • 攔截觸摸事件
  • tracking屬性變為YES
  • 一個內置的計時器開始生效,用來監控在極短的事件間隔內是否發生了手指移動

case1:當檢測到時間間隔內手指發生了移動,UIScrollView自己觸發滾動,tracking屬性變為NO,手指觸摸下即使有(可以響應觸摸事件的)內部控件也不會再響應觸摸事件。
case2:當檢測到時間間隔內手指沒有移動,tracking屬性保持YES,手指觸摸下如果有(可以響應觸摸事件的)內部控件,則將觸摸事件傳遞給控件進行處理。

當你手指是緩慢劃過或根本就沒動,
才會觸發UIButton的觸摸事件,這是case1的情況;

有很多新聞類的App頂部都有一個滑動菜單欄,
主要模型可能是由一個UIScrollView包含多個UIButton控件組成;
當你操作的時候,手指如果是很迅速的在上面劃過,
會發現即使手指觸摸的地方有UIButton,
但是并沒有觸發該UIButton的任何觸摸事件,
這就是上面提到的case2。

上面的工作原理其實有一個屬性開關來控制:delaysContentTouches。
解釋:delaysContentTouches
一個BOOL值,該值決定了滾動視圖是否延遲了觸控手勢的處理。
默認值為YES;如果設置為NO,則無論手指移動的多么快,
始終都會將觸摸事件傳遞給內部控件;
設置為NO可能會影響到UIScrollView的滾動功能。

delaysContentTouches的作用:
這個標志默認是YES,使用上面的150ms的timer,
如果設置為NO,touch事件立即傳遞給subView,
不會有150ms的等待。

delaysContentTouches :默認是YES;如果設置為NO,會馬上執行touchesShouldBegin:withEvent:inContentView:

- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches
                 withEvent:(UIEvent *)event 
             inContentView:(UIView *)view;


系統默認是允許UIScrollView,按照消息響應鏈向子視圖傳遞消息的。(即返回YES)
如果你不想UIScrollView的子視圖接受消息,返回NO。

應用描述(本人注釋):這個方法是最先接收到滑動事件的(優先于button的
UIControlEventTouchDown,以及
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event),
如果返回YES,touche事件沿著消息響應鏈傳遞;
如果返回NO,表示UIScrollView接收這個滾動事件,不必沿著消息響應鏈傳遞了。
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
應用描述(本人注釋):
如果返回YES:(系統默認)是允許UIScrollView,按照消息響應鏈向子視圖傳遞消息的
如果返回NO:UIScrollView,就接收不到滑動事件了。

再看另一個BOOL類型的屬性canCancelContentTouches,
從字面上理解是“可以取消內容觸摸“,默認值為YES。
這個BOOL類型的值控制content view里的觸摸是否總能引發跟蹤(tracking)
cancelsTouches的作用:
應用描述(本人注釋):默認設置為YES,如果設置為NO,
這消息一旦傳遞給subView,這scroll事件不會再發生。

如果屬性值為YES并且跟蹤到手指正觸摸到一個內容控件,這時如果用戶拖動手指的距離足夠產生滾動,那么內容控件將收到一個touchesCancelled:withEvent:消息,而scroll view將這次觸摸作為滾動來處理。如果值為NO,一旦content view開始跟蹤(tracking==YES),則無論手指是否移動,scrollView都不會滾動。

  • 簡單點說,如果為YES,就會等待用戶下一步動作,如果用戶移動手指到一定距離,就會把這個操作作為滾動來處理并開始滾動,同時發送一個touchesCancelled:withEvent:消息給內容控件,由控件自行處理。如果為NO,就不會等待用戶下一步動作,并始終不會觸發scrollView的滾動了。
  • 可以用一段代碼來驗證并觀察一下,定義一個YGScrollView繼承自UIScrollView,一個YGButton繼承自UIButton,然后重寫部分方法:
//【code_小馬】
YGScrollView.m

- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
    [super touchesShouldCancelInContentView:view];
    
    NSLog(@"code_小馬:touchesShouldCancelInContentView");
    
    return YES;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
    
    NSLog(@"code_小馬:touchesCancelled");
}

//【code_小馬】
YGButton.m


- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
    
    NSLog(@"【code_小馬:Button's touch cancelled】");
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    
    NSLog(@"【code_小馬:Button's touch began】");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    
    NSLog(@"【code_小馬:Button's touch moved】");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    NSLog(@"【code_小馬: Button's touch ended】");
}

其實就是在各個方法執行時打印出一個標記,

  • 當canCencelContentTouches值為YES時,
    用戶觸摸并移動手指再放開:輸出臺

【code_小馬: Button's touch began】
【code_小馬: Button's touch moved】
……
【code_小馬: Button's touch moved】
code_小馬:touchesShouldCancelInContentView
【code_小馬: Button's touch cancelled】

  • 當canCencelContentTouches值為NO時,
    用戶觸摸并移動手指再放開:輸出臺

【code_小馬:Button's touch began】
【code_小馬:Button's touch moved】
……
【code_小馬:Button's touch moved】
【code_小馬:Button's touch ended】

【code_小馬】iOS實用戰術
本文源碼下載

晌午時光

  • 很喜歡的一篇文章,拿出來和大家分享
    【第四集】

那天我在巷口看見了如風攔住阿福,我剛想走過去卻聽到如風說:“別來我家了?!薄  盀槭裁??你姐是街里最漂亮的女孩子!我很中意她!”阿福笑著說。  “別來找我姐了?!比顼L說?!  鞍L啊,你好福氣的!我要是能天天和她睡一間屋,死了也心甘啦……”阿福仍繼續說著,但他還沒有說完,就被如風打倒在了地上。    “你瘋啦!”阿福怒氣沖沖的爬起來,揮起拳頭就向如風打去,轉眼間兩個人就扭打成了一團。我驚訝的站在一旁,卻沒想過去拉開他們,因為我看到雖然阿福比如風高大,但卻是如風占了上風,如風打得狠,拼命的狠。還有,就是我想知道,如風為什么為了不讓阿福找我而和他打架?! 〔灰粫⒏>透骛埩耍顼L的臉也腫了起來,他不依不饒的說:“別再找我姐,不然我見一次打一次?!卑⒏_B連答應,戰戰兢兢的走出小巷,看見我居然都沒敢說一句話?!   ∥覜]瞧他一眼就走到如風身邊,摸摸他腫脹的臉說:“疼不?”     如風搖搖頭,避開我的手?!   ∥矣悬c生氣,討厭他不理我的態度,板著臉說:“干嗎打阿福?”    他不說話,我更生氣,說:“怪不得虎哥安仔都不來找我了,都是你干的吧!”    如風抬起頭,望著我,一字一句的說:“姐,只有我一個不好嗎?”    他的眼神很純凈,純凈且堅定?!   ∥液退麑ν!   ≈挥腥顼L一個人嗎?他雖然不愛說話,但和他在一起卻比和談天說地的阿福在一起舒服,而這種舒服是無處不在的?!   ∷麜€了好幾月的錢,買我最愛吃的豆沙餡粽子回來。其實我從來沒說過自己喜歡豆沙,能有粽子吃還挑選餡料是很奢侈的事情,只是很久以前那次吃粽子,我唯獨吃了豆沙的兩只,他便默默記下?!   ∷麜刻煸趯W校門口等我下學,很自然的拿過我的書包,為我撐傘,踮起腳尖把奶奶給他的圍巾圍在我脖子上。    他會在我噘著嘴洗碗時,走到我身邊把我擠開,粗手粗腳的在池子邊干起來。當我不小心把盤子摔壞的時候,會大聲對奶奶說:“是我做的!”    我突然發現,原來瘦瘦小小的如風一直站在我身邊,當虎哥、安仔、阿福都不在時,他永遠站在那里。而我,很開心他這樣子。    “好,只有你一個!”我笑著捧著他的臉說,他很害臊似的躲開我的手,但眼神里是說不盡的快樂?!   「羧眨⒏屢姷侥棠踢溃骸澳慵茵B了只狼仔!”奶奶沒說如風什么,她總是不說他的,只是時不時的搖頭。    此后,再也沒有誰來找我了,我也漸漸不再和別人打交道?!   ∧悄?,我13歲,魏如風12歲?!   ∧棠虥]有任何征兆的離開我們了。    開始她只是有些感冒,不停地咳嗽,我勸她去醫院但她卻死活不肯:“明日就好了,去花什么錢!你以為那些大夫就醫得好?還不是騙你白花好些個!不如多喝些水哩!”    奶奶的明日遲遲不來,末日卻終于臨近。那天傍晚我們放學回來,奶奶在椅子上已經彌留了,她盯著弟弟看了很久,最后看了我一眼,嘆了口氣,沒說一句話睜著眼睛就離開了。我當夜哭得死去活來,如風一直攥著我的手,片刻不離........................

文章第三集
文章第五集
后續更新中,喜歡的話 請關注 ??【code_小馬】?? 哦

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

推薦閱讀更多精彩內容