ios-晉級之路 tableViewCell中添加ScrollView觸摸事件的問題


今天博主做了這樣一個demo,上圖,圖中cell有點類似oc自帶刪除功能的cell,但是嫌棄他長得難看~~!博主自定義了一個cell   

Cell中有scrollView,這就出現問題了,因為這個cell是需要跳轉的,但是這個點擊事件被scrollView截取了,這就連帶出了很多問題,其中主要的就是響應者鏈條。

這里也看了很多博文,感覺這個比較好:

響應者鏈條概念: iOS系統檢測到手指觸摸(Touch)操作時會將其打包成一個UIEvent對象,並放入當前活動Application的事件隊列,單例的UIApplication會從事件隊列中取出觸摸事件並傳遞給單例的UIWindow來處理,UIWindow對象首先會使用hitTest:withEvent:方法尋找此次Touch操作初始點所在的視圖(View),即需要將觸摸事件傳遞給其處理的視圖,這個過程稱之為hit-test view。
響應者對象(Responder Object) 指的是 有響應和處理事件能力的對象。 響應者鏈就是由一系列的響應者對象 構成的一個層次結構。
UIResponder 是所有響應對象的基類,在UIResponder類中定義了處理上述各種事件的接口。我們熟悉的 UIApplication、 UIViewController、 UIWindow 和所有繼承自UIView的UIKit類都直接或間接的繼承自UIResponder,所以它們的實例都是可以構成響應者鏈的響應者對象。
UIWindow實例對象會首先在它的內容視圖上調用hitTest:withEvent:,此方法會在其視圖層級結構中的每個視圖上調用pointInside:withEvent:(該方法用來判斷點擊事件發生的位置是否處於當前視圖范圍內,以確定用戶是不是點擊了當前視圖),如果pointInside:withEvent:返回YES,則繼續逐級調用,直到找到touch操作發生的位置,這個視圖也就是要找的hit-test view。

hitTest:withEvent:方法的處理流程如下: 
首先調用當前視圖的pointInside:withEvent:方法判斷觸摸點是否在當前視圖內; 
若返回NO,則hitTest:withEvent:返回nil; 
若返回YES,則向當前視圖的所有子視圖(subviews)發送hitTest:withEvent:消息,所有子視圖的遍歷順序是從最頂層視圖一直到到最底層視圖,即從subviews數組的末尾向前遍歷,直到有子視圖返回非空對象或者全部子視圖遍歷完畢; 
若第一次有子視圖返回非空對象,則hitTest:withEvent:方法返回此對象,處理結束; 
如所有子視圖都返回非,則hitTest:withEvent:方法返回自身(self)。

 

響應者鏈條是從點擊的當前控件中自上而下的,如果當前控件不能處理點擊事件的話再向下傳遞,如果處理點擊事件的話會執行三個方法(還有一個就先不說了):

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

{

    [super touchesBegan:touches withEvent:event];

}

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

{

    [super touchesMoved:touches withEvent:event];

}

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

{

    [super touchesEnded:touches withEvent:event];

}

但是經過測試發現scrollView中只有點擊事件才會執行此三種方法,而滑動事件則不會。而我們正是要的這種效果,如果滑動的話界面是不跳轉的,點擊才跳轉,在這里我們在scrollView中這樣操作

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

{

    albumTableViewCell * cell = self.superview;

    [cell touchesBegan:touches withEvent:event];

}

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

{

    albumTableViewCell * cell = self.superview;

    [cell touchesEnded:touches withEvent:event];

}

其實只寫touchesend那個方法就可以,將點擊事件傳遞下去,在執行了touchEnd之后tableView的代理方法didSelect才會執行

,這樣實現了點擊事件的手動傳遞,效果還是不錯的~~!

順便說一下關閉控件響應事件的三種方法,一個是屬性userInteractionEnabled設成No、hidden屬性設成yes、alpha在0~0.01之間,其實還有一種,就是重寫控件將hitTest:withEvent:方法,將返回置為空(因為響應者鏈條是這個方法傳遞的)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM