UIScrollView高級用法:delaysContentTouches與canCencelContentTouches屬性

需求:UIScrollView+btns。點擊btn高亮(Highlighted),滑動UIScrollView時取消高亮;研究了一下,整理如下:

1.實現:點擊btn高亮(Highlighted),且滑動UIScrollView時保持高亮狀態,是不合理的,無法實現的。

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。

官方解釋:

A Boolean value that determines whether the scroll view delays the handling of touch-down gestures.

中文翻譯:

一個布爾值,該值決定了滾動視圖是否延遲了觸控手勢的處理。

默認值為YES;如果設置為NO,則無論手指移動的多么快,始終都會將觸摸事件傳遞給內部控件;設置為NO可能會影響到UIScrollView的滾動功能。

delaysContentTouches的作用:

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

Discussion

If the value of this property isYES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value isNO, the scroll view immediately callstouchesShouldBegin:withEvent:inContentView:. The default value isYES.

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

- (BOOL)touchesShouldBegin:(NSSet<UITouch*> *)toucheswithEvent:(UIEvent*)event

inContentView:(UIView*)view

Discussion

The default behavior ofUIScrollViewis to invoke theUIResponderevent-handling methods of the target subview that the touches occur in.

系統默認是允許UIScrollView,按照消息響應鏈向子視圖傳遞消息的。(即返回YES)

Return Value

ReturnNOif you don’t want the scroll view to send event messages toview. If you wantviewto receive those messages, returnYES(the default).

如果你不想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。文檔里的解釋是這樣的:

A Boolean value that controls whether touches in the content view always lead to tracking.

If the value of this property is YES and a view in the content has begun

tracking a finger touching it, and if the user drags the finger enough

to initiate a scroll, the view receives a touchesCancelled:withEvent:

message and the scroll view handles the touch

as a scroll. If the value of this property is NO, the scroll view does

not scroll regardless of finger movement once the content view starts

tracking.

翻譯為中文大致如下:

這個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的滾動了。

可以用一段代碼來驗證并觀察一下,定義一個MyScrollView繼承自UIScrollView,一個MyButton繼承自UIButton,然后重寫部分方法:

MyScrollView.m

- (BOOL)touchesShouldCancelInContentView:(UIView *)view

{

[super touchesShouldCancelInContentView:view];

NSLog(@"touchesShouldCancelInContentView");returnYES;

}- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesCancelled:touches withEvent:event];

NSLog(@"touchesCancelled");

}

MyButton.m

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesCancelled:touches withEvent:event];

NSLog(@"【Button's touch cancelled】");

}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesBegan:touches withEvent:event];

NSLog(@"【Button's touch began】");

}- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesMoved:touches withEvent:event];

NSLog(@"【Button's touch moved】");

}- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

[super touchesEnded:touches withEvent:event];

NSLog(@"【Button's touch ended】");

}

其實就是在各個方法執行時打印出一個標記,當canCencelContentTouches值為YES時,用戶觸摸并移動手指再放開:

【Button's touch began】

【Button's touch moved】

……

【Button's touch moved】

touchesShouldCancelInContentView

【Button's touch cancelled】

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

【Button's touch began】

【Button's touch moved】

……

【Button's touch moved】

【Button's touch ended】

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

推薦閱讀更多精彩內容