UIScrollView高級用法:delaysContentTouches與canCencelContentTouches屬性

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

1.實現(xiàn):點擊btn高亮(Highlighted)牵素,且滑動UIScrollView時保持高亮狀態(tài),是不合理的澄者,無法實現(xiàn)的笆呆。

2.實現(xiàn):點擊btn高亮(Highlighted)请琳,滑動UIScrollView時取消高亮狀態(tài),是可以做到的赠幕。

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

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

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

1.150ms內(nèi)如果你的手指沒有任何動作,消息就會傳給subView局冰。

2.150ms內(nèi)手指有明顯的滑動(一個swipe動作),scrollView就會滾動灌危,消息不會傳給subView康二。

3. ?150ms內(nèi)手指沒有滑動,scrollView將消息傳給subView勇蝙,但是之后手指開始滑動沫勿,scrollView傳送touchesCancelled消息給subView,然后開始滾動味混。

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

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

當(dāng)手指觸摸到UIScrollView內(nèi)容的一瞬間,會產(chǎn)生下面的動作:

攔截觸摸事件

tracking屬性變?yōu)閅ES

一個內(nèi)置的計時器開始生效趟畏,用來監(jiān)控在極短的事件間隔內(nèi)是否發(fā)生了手指移動

case1:當(dāng)檢測到時間間隔內(nèi)手指發(fā)生了移動蕉扮,UIScrollView自己觸發(fā)滾動,tracking屬性變?yōu)镹O角溃,手指觸摸下即使有(可以響應(yīng)觸摸事件的)內(nèi)部控件也不會再響應(yīng)觸摸事件拷获。

case2:當(dāng)檢測到時間間隔內(nèi)手指沒有移動,tracking屬性保持YES减细,手指觸摸下如果有(可以響應(yīng)觸摸事件的)內(nèi)部控件匆瓜,則將觸摸事件傳遞給控件進(jìn)行處理。

當(dāng)你手指是緩慢劃過或根本就沒動未蝌,才會觸發(fā)UIButton的觸摸事件驮吱,這是case1的情況;

有很多新聞類的App頂部都有一個滑動菜單欄树埠,主要模型可能是由一個UIScrollView包含多個UIButton控件組成糠馆;當(dāng)你操作的時候,手指如果是很迅速的在上面劃過怎憋,會發(fā)現(xiàn)即使手指觸摸的地方有UIButton又碌,但是并沒有觸發(fā)該UIButton的任何觸摸事件九昧,這就是上面提到的case2。

上面的工作原理其實有一個屬性開關(guān)來控制:delaysContentTouches毕匀。

官方解釋:

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

中文翻譯:

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

默認(rèn)值為YES皂岔;如果設(shè)置為NO蹋笼,則無論手指移動的多么快,始終都會將觸摸事件傳遞給內(nèi)部控件躁垛;設(shè)置為NO可能會影響到UIScrollView的滾動功能剖毯。

delaysContentTouches的作用:

這個標(biāo)志默認(rèn)是YES,使用上面的150ms的timer教馆,如果設(shè)置為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.

默認(rèn)YES胶滋;如果設(shè)置為NO,會馬上執(zhí)行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.

系統(tǒng)默認(rèn)是允許UIScrollView悲敷,按照消息響應(yīng)鏈向子視圖傳遞消息的究恤。(即返回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后德。

應(yīng)用描述(作者注釋):這個方法是最先接收到滑動事件的(優(yōu)先于button的

UIControlEventTouchDown部宿,以及- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event),

如果返回YES瓢湃,touche事件沿著消息響應(yīng)鏈傳遞;

如果返回NO窟赏,表示UIScrollView接收這個滾動事件,不必沿著消息響應(yīng)鏈傳遞了箱季。

- (BOOL)touchesShouldCancelInContentView:(UIView*)view

應(yīng)用描述(作者注釋):

如果返回YES:(系統(tǒng)默認(rèn))是允許UIScrollView涯穷,按照消息響應(yīng)鏈向子視圖傳遞消息的

如果返回NO:UIScrollView,就接收不到滑動事件了。

再看另一個BOOL類型的屬性canCancelContentTouches藏雏,從字面上理解是“可以取消內(nèi)容觸摸“拷况,默認(rèn)值為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里的觸摸是否總能引發(fā)跟蹤(tracking)

cancelsTouches的作用:

應(yīng)用描述(作者注釋):

默認(rèn)設(shè)置為YES掘殴,

如果設(shè)置為NO赚瘦,這消息一旦傳遞給subView,這scroll事件不會再發(fā)生奏寨。

如果屬性值為YES并且跟蹤到手指正觸摸到一個內(nèi)容控件起意,這時如果用戶拖動手指的距離足夠產(chǎn)生滾動,那么內(nèi)容控件將收到一個touchesCancelled:withEvent:消息病瞳,而scroll

view將這次觸摸作為滾動來處理揽咕。如果值為NO悲酷,一旦content

view開始跟蹤(tracking==YES),則無論手指是否移動亲善,scrollView都不會滾動设易。

簡單通俗點說,如果為YES蛹头,就會等待用戶下一步動作顿肺,如果用戶移動手指到一定距離,就會把這個操作作為滾動來處理并開始滾動渣蜗,同時發(fā)送一個touchesCancelled:withEvent:消息給內(nèi)容控件屠尊,由控件自行處理。如果為NO耕拷,就不會等待用戶下一步動作知染,并始終不會觸發(fā)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】");

}

其實就是在各個方法執(zhí)行時打印出一個標(biāo)記止潘,當(dāng)canCencelContentTouches值為YES時,用戶觸摸并移動手指再放開:

【Button's touch began】

【Button's touch moved】

……

【Button's touch moved】

touchesShouldCancelInContentView

【Button's touch cancelled】

當(dāng)canCencelContentTouches值為NO時辫诅,用戶觸摸并移動手指再放開:

【Button's touch began】

【Button's touch moved】

……

【Button's touch moved】

【Button's touch ended】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凭戴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炕矮,更是在濱河造成了極大的恐慌么夫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肤视,死亡現(xiàn)場離奇詭異档痪,居然都是意外死亡,警方通過查閱死者的電腦和手機邢滑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門腐螟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人困后,你說我怎么就攤上這事乐纸。” “怎么了摇予?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵汽绢,是天一觀的道長。 經(jīng)常有香客問我侧戴,道長宁昭,這世上最難降的妖魔是什么跌宛? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮久窟,結(jié)果婚禮上秩冈,老公的妹妹穿的比我還像新娘。我一直安慰自己斥扛,他們只是感情好入问,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稀颁,像睡著了一般芬失。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匾灶,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天棱烂,我揣著相機與錄音,去河邊找鬼阶女。 笑死颊糜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秃踩。 我是一名探鬼主播衬鱼,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼憔杨!你這毒婦竟也來了鸟赫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤消别,失蹤者是張志新(化名)和其女友劉穎抛蚤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寻狂,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡岁经,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛇券。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒿偎。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怀读,靈堂內(nèi)的尸體忽然破棺而出诉位,到底是詐尸還是另有隱情,我是刑警寧澤菜枷,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布苍糠,位于F島的核電站,受9級特大地震影響啤誊,放射性物質(zhì)發(fā)生泄漏岳瞭。R本人自食惡果不足惜拥娄,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞳筏。 院中可真熱鬧稚瘾,春花似錦、人聲如沸姚炕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柱宦。三九已至些椒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掸刊,已是汗流浹背免糕。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忧侧,地道東北人石窑。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蚓炬,于是被迫代替她去往敵國和親松逊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

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