
老樣子,先上代碼解燃眉之急,具體思路解釋 見下文
- 開源代碼在github上直接下載
下載鏈接: https://github.com/McodeYG/-code_-ScrollView-Btn
/*UIScrollView高級(jí)用法:
delaysContentTouches與
canCencelContentTouches屬性*/
需求:
UIScrollView+btns。點(diǎn)擊btn高亮(Highlighted),滑動(dòng)UIScrollView時(shí)取消高亮;
分析:
1.實(shí)現(xiàn):點(diǎn)擊btn高亮(Highlighted),且滑動(dòng)UIScrollView時(shí)保持高亮狀態(tài),是不合理的,無法實(shí)現(xiàn)的。(ps還不如直接用cell或者btn的選中狀態(tài))
2.實(shí)現(xiàn):點(diǎn)擊btn高亮(Highlighted), 滑動(dòng)UIScrollView時(shí)取消高亮狀態(tài),是可以做到的。
按照從不同的要素去解釋原理:
一、UIScrollView原理,以時(shí)間為軸線:
從你的手指touch屏幕開始,scrollView開始一個(gè)timer,如果:
- 150ms內(nèi)如果你的手指沒有任何動(dòng)作,消息就會(huì)傳給subView。
- 150ms內(nèi)手指有明顯的滑動(dòng)(一個(gè)swipe動(dòng)作),scrollView就會(huì)滾動(dòng),消息不會(huì)傳給subView。
- 150ms內(nèi)手指沒有滑動(dòng),scrollView將消息傳給subView,但是之后手指開始滑動(dòng),scrollView傳送touchesCancelled消息給subView,然后開始滾動(dòng)。
二、UIScrollView原理,以tracking屬性為軸線:
UIScrollView有一個(gè)BOOL類型的tracking屬性,用來返回用戶是否已經(jīng)觸及內(nèi)容并打算開始滾動(dòng),我們從這個(gè)屬性開始探究UIScrollView的工作原理:
當(dāng)手指觸摸到UIScrollView內(nèi)容的一瞬間,會(huì)有以下動(dòng)作:
- 攔截觸摸事件
- tracking屬性變?yōu)閅ES
- 一個(gè)內(nèi)置的計(jì)時(shí)器開始生效,用來監(jiān)控在極短的事件間隔內(nèi)是否發(fā)生了手指移動(dòng)
case1:當(dāng)檢測(cè)到時(shí)間間隔內(nèi)手指發(fā)生了移動(dòng),UIScrollView自己觸發(fā)滾動(dòng),tracking屬性變?yōu)镹O,手指觸摸下即使有(可以響應(yīng)觸摸事件的)內(nèi)部控件也不會(huì)再響應(yīng)觸摸事件。
case2:當(dāng)檢測(cè)到時(shí)間間隔內(nèi)手指沒有移動(dòng),tracking屬性保持YES,手指觸摸下如果有(可以響應(yīng)觸摸事件的)內(nèi)部控件,則將觸摸事件傳遞給控件進(jìn)行處理。
當(dāng)你手指是緩慢劃過或根本就沒動(dòng),
才會(huì)觸發(fā)UIButton的觸摸事件,這是case1的情況;
有很多新聞?lì)惖腁pp頂部都有一個(gè)滑動(dòng)菜單欄,
主要模型可能是由一個(gè)UIScrollView包含多個(gè)UIButton控件組成;
當(dāng)你操作的時(shí)候,手指如果是很迅速的在上面劃過,
會(huì)發(fā)現(xiàn)即使手指觸摸的地方有UIButton,
但是并沒有觸發(fā)該UIButton的任何觸摸事件,
這就是上面提到的case2。
上面的工作原理其實(shí)有一個(gè)屬性開關(guān)來控制:delaysContentTouches。
解釋:delaysContentTouches
一個(gè)BOOL值,該值決定了滾動(dòng)視圖是否延遲了觸控手勢(shì)的處理。
默認(rèn)值為YES;如果設(shè)置為NO,則無論手指移動(dòng)的多么快,
始終都會(huì)將觸摸事件傳遞給內(nèi)部控件;
設(shè)置為NO可能會(huì)影響到UIScrollView的滾動(dòng)功能。
delaysContentTouches的作用:
這個(gè)標(biāo)志默認(rèn)是YES,使用上面的150ms的timer,
如果設(shè)置為NO,touch事件立即傳遞給subView,
不會(huì)有150ms的等待。
delaysContentTouches :默認(rèn)是YES;如果設(shè)置為NO,會(huì)馬上執(zhí)行touchesShouldBegin:withEvent:inContentView:
- (BOOL)touchesShouldBegin:(NSSet<UITouch *> *)touches
withEvent:(UIEvent *)event
inContentView:(UIView *)view;
系統(tǒng)默認(rèn)是允許UIScrollView,按照消息響應(yīng)鏈向子視圖傳遞消息的。(即返回YES)
如果你不想U(xiǎn)IScrollView的子視圖接受消息,返回NO。
應(yīng)用描述(本人注釋):這個(gè)方法是最先接收到滑動(dòng)事件的(優(yōu)先于button的
UIControlEventTouchDown,以及
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event),
如果返回YES,touche事件沿著消息響應(yīng)鏈傳遞;
如果返回NO,表示UIScrollView接收這個(gè)滾動(dòng)事件,不必沿著消息響應(yīng)鏈傳遞了。
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
應(yīng)用描述(本人注釋):
如果返回YES:(系統(tǒng)默認(rèn))是允許UIScrollView,按照消息響應(yīng)鏈向子視圖傳遞消息的
如果返回NO:UIScrollView,就接收不到滑動(dòng)事件了。
再看另一個(gè)BOOL類型的屬性canCancelContentTouches,
從字面上理解是“可以取消內(nèi)容觸摸“,默認(rèn)值為YES。
這個(gè)BOOL類型的值控制content view里的觸摸是否總能引發(fā)跟蹤(tracking)
cancelsTouches的作用:
應(yīng)用描述(本人注釋):默認(rèn)設(shè)置為YES,如果設(shè)置為NO,
這消息一旦傳遞給subView,這scroll事件不會(huì)再發(fā)生。
如果屬性值為YES并且跟蹤到手指正觸摸到一個(gè)內(nèi)容控件,這時(shí)如果用戶拖動(dòng)手指的距離足夠產(chǎn)生滾動(dòng),那么內(nèi)容控件將收到一個(gè)touchesCancelled:withEvent:消息,而scroll view將這次觸摸作為滾動(dòng)來處理。如果值為NO,一旦content view開始跟蹤(tracking==YES),則無論手指是否移動(dòng),scrollView都不會(huì)滾動(dòng)。
- 簡(jiǎn)單點(diǎn)說,如果為YES,就會(huì)等待用戶下一步動(dòng)作,如果用戶移動(dòng)手指到一定距離,就會(huì)把這個(gè)操作作為滾動(dòng)來處理并開始滾動(dòng),同時(shí)發(fā)送一個(gè)touchesCancelled:withEvent:消息給內(nèi)容控件,由控件自行處理。如果為NO,就不會(huì)等待用戶下一步動(dòng)作,并始終不會(huì)觸發(fā)scrollView的滾動(dòng)了。
- 可以用一段代碼來驗(yàn)證并觀察一下,定義一個(gè)YGScrollView繼承自UIScrollView,一個(gè)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】");
}
其實(shí)就是在各個(gè)方法執(zhí)行時(shí)打印出一個(gè)標(biāo)記,
- 當(dāng)canCencelContentTouches值為YES時(shí),
用戶觸摸并移動(dòng)手指再放開:輸出臺(tái)
【code_小馬: Button's touch began】
【code_小馬: Button's touch moved】
……
【code_小馬: Button's touch moved】
code_小馬:touchesShouldCancelInContentView
【code_小馬: Button's touch cancelled】
- 當(dāng)canCencelContentTouches值為NO時(shí),
用戶觸摸并移動(dòng)手指再放開:輸出臺(tái)
【code_小馬:Button's touch began】
【code_小馬:Button's touch moved】
……
【code_小馬:Button's touch moved】
【code_小馬:Button's touch ended】
【code_小馬】iOS實(shí)用戰(zhàn)術(shù)
本文源碼下載
晌午時(shí)光
- 很喜歡的一篇文章,拿出來和大家分享
【第四集】
那天我在巷口看見了如風(fēng)攔住阿福,我剛想走過去卻聽到如風(fēng)說:“別來我家了?!薄 盀槭裁??你姐是街里最漂亮的女孩子!我很中意她!”阿福笑著說?! 皠e來找我姐了。”如風(fēng)說。 “阿風(fēng)啊,你好福氣的!我要是能天天和她睡一間屋,死了也心甘啦……”阿福仍繼續(xù)說著,但他還沒有說完,就被如風(fēng)打倒在了地上?! 澳惘偫?!”阿福怒氣沖沖的爬起來,揮起拳頭就向如風(fēng)打去,轉(zhuǎn)眼間兩個(gè)人就扭打成了一團(tuán)。我驚訝的站在一旁,卻沒想過去拉開他們,因?yàn)槲铱吹诫m然阿福比如風(fēng)高大,但卻是如風(fēng)占了上風(fēng),如風(fēng)打得狠,拼命的狠。還有,就是我想知道,如風(fēng)為什么為了不讓阿福找我而和他打架?! 〔灰粫?huì),阿福就告饒了,如風(fēng)的臉也腫了起來,他不依不饒的說:“別再找我姐,不然我見一次打一次?!卑⒏_B連答應(yīng),戰(zhàn)戰(zhàn)兢兢的走出小巷,看見我居然都沒敢說一句話?! ∥覜]瞧他一眼就走到如風(fēng)身邊,摸摸他腫脹的臉說:“疼不?” 如風(fēng)搖搖頭,避開我的手?! ∥矣悬c(diǎn)生氣,討厭他不理我的態(tài)度,板著臉說:“干嗎打阿福?” 他不說話,我更生氣,說:“怪不得虎哥安仔都不來找我了,都是你干的吧!” 如風(fēng)抬起頭,望著我,一字一句的說:“姐,只有我一個(gè)不好嗎?” 他的眼神很純凈,純凈且堅(jiān)定?! ∥液退麑?duì)望。 只有如風(fēng)一個(gè)人嗎?他雖然不愛說話,但和他在一起卻比和談天說地的阿福在一起舒服,而這種舒服是無處不在的?! ∷麜?huì)攢了好幾月的錢,買我最愛吃的豆沙餡粽子回來。其實(shí)我從來沒說過自己喜歡豆沙,能有粽子吃還挑選餡料是很奢侈的事情,只是很久以前那次吃粽子,我唯獨(dú)吃了豆沙的兩只,他便默默記下?! ∷麜?huì)每天在學(xué)校門口等我下學(xué),很自然的拿過我的書包,為我撐傘,踮起腳尖把奶奶給他的圍巾圍在我脖子上?! ∷麜?huì)在我噘著嘴洗碗時(shí),走到我身邊把我擠開,粗手粗腳的在池子邊干起來。當(dāng)我不小心把盤子摔壞的時(shí)候,會(huì)大聲對(duì)奶奶說:“是我做的!” 我突然發(fā)現(xiàn),原來瘦瘦小小的如風(fēng)一直站在我身邊,當(dāng)虎哥、安仔、阿福都不在時(shí),他永遠(yuǎn)站在那里。而我,很開心他這樣子。 “好,只有你一個(gè)!”我笑著捧著他的臉說,他很害臊似的躲開我的手,但眼神里是說不盡的快樂?! 「羧眨⒏屢姷侥棠踢溃骸澳慵茵B(yǎng)了只狼仔!”奶奶沒說如風(fēng)什么,她總是不說他的,只是時(shí)不時(shí)的搖頭。 此后,再也沒有誰(shuí)來找我了,我也漸漸不再和別人打交道。 那年,我13歲,魏如風(fēng)12歲?! ∧棠虥]有任何征兆的離開我們了?! ¢_始她只是有些感冒,不停地咳嗽,我勸她去醫(yī)院但她卻死活不肯:“明日就好了,去花什么錢!你以為那些大夫就醫(yī)得好?還不是騙你白花好些個(gè)!不如多喝些水哩!” 奶奶的明日遲遲不來,末日卻終于臨近。那天傍晚我們放學(xué)回來,奶奶在椅子上已經(jīng)彌留了,她盯著弟弟看了很久,最后看了我一眼,嘆了口氣,沒說一句話睜著眼睛就離開了。我當(dāng)夜哭得死去活來,如風(fēng)一直攥著我的手,片刻不離........................