UISCroll View 原理

文章來源:http://blog.csdn.net/gavinming/article/details/6552565

最近看到有人問這個問題:在UIScrollView上添加了一個View,View上面有圖片等元素,需要對單擊和滑動事件進行區分。這樣的問題有以下幾個經常會用到的地方:

     (1)點擊UIScrollView上的圖片,跳轉到其他頁面;同時不影響UIScrollView的滑動操作。

     (2)在閱讀瀏覽類產品會經常用到,點擊屏幕的中間區域,隱藏/顯示狀態欄或導航條;同時不影響UIScrollView的滑動翻頁操作。

 

       有解決方法事在點擊區域添加一個透明的Button,但個人感覺比較複雜,而且效果並不好。以下是我個人的解決方法:

 

       首先了解下UIScrollView對於touch事件的接收處理原理:UIScrollView重載hitTest 方法,並總會返回itself 。所以所有的touch 事件都會進入到它自己裏面去了。內部的touch事件檢測到這個事件是不是和自己相關的,或者處理或者除遞給內部的view。

       爲了檢測touch是處理還是傳遞,UIScrollView當touch產生一個timer。

(1)如果150ms內touch未產生移動,它就把這個事件傳遞給內部view;

(2)如果150ms內touch產生移動,開始scrolling,不會傳遞給內部的view。(如當你touch一個table時候,直接scrolling,你touch的那行永遠不會highlight。)

(3)如果150ms內touch未產生移動並且UIScrollView開始傳遞內部的view事件,但是移動足夠遠的話,且canCancelContentTouches = YES,UIScrollView會調用touchesCancelled方法,cancel掉內部view的事件響應,並開始scrolling。(如當你touch一個table, 停止了一會,然後開始scrolling,那一行就首先被highlight,但是隨後就不在高亮了)

 

       先前提到的在UIScrollView內部的view點擊區域添加透明Button的解決方法,就是需要設置canCancelContentTouches = YES,而且還需重寫UIScrollView的touchesShouldCancelInContentView:(UIView *)view方法,在view爲UIButton的時候,返回YES。不然點擊到button上的事件已經被button接收了,無法cancle掉。另外針對閱讀瀏覽頁面,一般手指都會停留在UIScrollView滾動,如果需要隱藏/顯示狀態欄或導航條,則會出現每點擊一次就出現隱藏/顯示問題。

 

       解決方法:該問題主要的難題要判斷單擊事件。由於150ms很小,因此基本上手指一接觸到UIScrollView就會傳遞到內部的view上,此時內部的view需對這個touch進行時間節點的判斷,判斷它是一個單擊事件,然後執行單擊操作。

 

 

 

 1、TestView是ScrollView的subview,也可也是繼承UIScrollView

 

TestView.h

  1. @interface TestView : UIView  
  2. {  
  3.     UIImageView *imageView;   
  4.     NSTimeInterval touchTimer; //記錄touch時間,來控制點擊和滑動判斷  
  5. }  
  6. @property(nonatomic, retain) UIImageView *imageView;  
  7. @property(nonatomic, assign) NSTimeInterval touchTimer;  
 

 

TestView.m

 

  1. @implementation TestView  
  2. #pragma mark -  
  3. #pragma mark Touch Method  
  4. @synthesize imageView;  
  5. @synthesize touchTimer;  
  6.   
  7. //thouchesBegan 獲取到touch的時間點  
  8. - (void)touchesBegan:(NSSet *)touches   
  9.            withEvent:(UIEvent *)event  
  10. {  
  11.     UITouch *touch = [touches anyObject];  
  12.     self.touchTimer = [touch timestamp];  
  13. }  
  14.   
  15.   
  16. //touchesEnded,touch事件完成,根據此時時間點獲取到touch事件的總時間,  
  17. - (void)touchesEnded:(NSSet *)touches   
  18.            withEvent:(UIEvent *)event  
  19. {  
  20.     UITouch *touch = [touches anyObject];  
  21.     self.touchTimer = [touch timestamp] - self.touchTimer;  
  22.       
  23.     NSUInteger tapCount = [touch tapCount];  
  24.     CGPoint touchPoint = [touch locationInView:self];  
  25.       
  26.     //判斷單擊事件,touch時間和touch的區域  
  27.     if (tapCount == 1 && self.touchTimer <= 3 && CGRectContainsPoint(self.imageView.frame, touchPoint))  
  28.     {  
  29.         //進行單擊的跳轉等事件  
  30.     }  
  31.       
  32. }  
發佈了6 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章