IOS view拖拽(觸摸事件)


• iOS中的事件可以分為3大類型


  1. 觸摸事件 
  2. 加速計事件
  3. 遠程控制事件     

 

 

響應者對象

iOS中不是任何對象都能處理事件,只有繼承了UIResponder的對象才能接收並處理事 件。我們稱之為響應者對象

UIApplicationUIViewControllerUIView都繼承自UIResponder,因此它們 都是響應者對象,都能夠接收並處理事件

 

 

UIResponder

UIResponder內部提供了以下方法來處理事件

觸摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

加速計事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

遠程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;

 

 

 

UIView的觸摸事件處理

UIViewUIResponder的子類,可以覆蓋下列4個方法處理不同的觸摸事件
一根或者多根手指開始觸摸view,系統會自動調用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

一根或者多根手指在view上移動,系統會自動調用view的下面方法(隨着手指的移動, 會持續調用該方法)

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 一根或者多根手指離開view,系統會自動調用view的下面方法

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
觸摸結束前,某個系統事件(例如電話呼入)會打斷觸摸過程,系統會自動調用view的下面

方法

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

提示:touches中存放的都是UITouch對象

 

 

UITouch

當用戶用一根觸摸屏幕時,會創建一個與手指相關聯的UITouch對象 一根手指對應一個UITouch對象

UITouch的作用
保存着跟手指相關的信息,比如觸摸的位置、時間、階段

當手指移動時,系統會更新同一個UITouch對象,使之能夠一直保存該手指在的觸摸位置 當手指離開屏幕時,系統會銷毀相應的UITouch對象
提示:iPhone開發中,要避免使用雙擊事件!

 

UITouch的屬性

觸摸產生時所處的窗口
 @property(nonatomic,readonly,retain) UIWindow *window;

 

觸摸產生時所處的視圖

 @property(nonatomic,readonly,retain) UIView *view;

 

短時間內點按屏幕的次數,可以根據tapCount判斷單擊、雙擊或更多的點擊

 @property(nonatomic,readonly) NSUInteger tapCount;

 

記錄了觸摸事件產生或變化時的時間,單位是秒

 @property(nonatomic,readonly) NSTimeInterval timestamp;

 

當前觸摸事件所處的狀態

@property(nonatomic,readonly) UITouchPhase phase; 
 

UITouch的方法

- ( CGPoint)locationInView:(UIView *)view;
  • 返回值表示觸摸在view上的位置
  • 這里返回的位置是針對view的坐標系的(以view的左上角為原點(0, 0))
  • 調用時傳入的view參數為nil的話,返回的是觸摸點在UIWindow的位置

- (CGPoint)previousLocationInView:(UIView *)view;

  • 該方法記錄了前一個觸摸點的位置

 

UIEvent

每產生一個事件,就會產生一個UIEvent對象
UIEvent:稱為事件對象,記錄事件產生的時刻類型

常見屬性
事件類型
@property(nonatomic,readonly) UIEventType type; @property(nonatomic,readonly) UIEventSubtype subtype;

事件產生的時間
@property(nonatomic,readonly) NSTimeInterval timestamp;

UIEvent還提供了相應的方法可以獲得在某個view上面的觸摸對象(UITouch)


 

touchesevent參數

一次完整的觸摸過程,會經歷3個狀態: 

觸摸開始:- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

觸摸移動:- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

觸摸結束:- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

觸摸取消(可能會經歷):- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

 

4個觸摸事件處理方法中,都有NSSet *touchesUIEvent *event兩個參數
如果兩根手指同時觸摸一個view,那么view只會調用一次touchesBegan:withEvent:

一次完整的觸摸過程中,只會產生一個事件對象,4個觸摸方法都是同一個event參數

      方法,touches參數中裝着2UITouch對象

如果這兩根手指一前一后分開觸摸同一個view,那么view會分別調用2 touchesBegan:withEvent:方法,並且每次調用  時 的touches參數中只包含一 個UITouch對象

根據touchesUITouch的個數可以判斷出是單點觸摸還是多點觸摸

 

 

事件的產生和傳遞

發生觸摸事件后,系統會將該事件加入到一個由UIApplication管理的事件隊列中
UIApplication會從事件隊列中取出最前面的事件,並將事件分發下去以便處理,通

常,先發送事件給應用程序的主窗又(keyWindow)
主窗又會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件,這也是整個事件處理

過程的第一步

找到合適的視圖控件后,就會調用視圖控件的touches方法來作具體的事件處理

touchesBegan...
touchesMoved...
touchedEnded...

 

 

事件傳遞示例

  • 觸摸事件的傳遞是從父控件傳遞到子控件
  • 如果父控件不能接收觸摸事件,那么子控件就不可能接收到觸摸事件(掌握)
  • 如何找到最合適的控件來處理事件?
  1. 自己是否能接收觸摸事件?
  2. 觸摸點是否在自己身上?
  3. 從后往前遍歷子控件,重復前面的兩個步驟
  4. 如果沒有符合條件的子控件,那么就自己最適合處理

 

UIView不接收觸摸事件的三種情況

 

  1. 不接收用戶交互 userInteractionEnabled = NO
  2. 隱藏                   hidden = YES
  3. 透明                   alpha = 0.0 ~ 0.01

提示:UIImageViewuserInteractionEnabled默認就是NO,因此UIImageView以 及它的子控件默認是不能接收觸摸事件的

 

 

// 觸摸事件完整的調用過程touchesBegan --> touchesMoved --> touchesEnded
// 當手指觸摸view的時候調用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//    [event allTouches] == touches
    
//    NSArray:用來保存同一種類型的有序的值
//    NSSet:  用來保存無序的值
//    NSArray *arr = @[@"1", @"2", @"3"];
//    arr[2];
//    NSSet set = @[@"2", @"3",@"1"];
    
//    UITouch *touch = [touches anyObject];
    // 獲取手指觸摸的位置
    // 如果locationInView傳遞self, 將來獲取出來的位置,是以自己的左上角為原點(00)
    // 如果傳遞的是父視圖,將來獲取出來的位置,是以父視圖的左上角為原點(00)
//    CGPoint point = [touch locationInView:self.superview];
//    NSLog(@"touchesBegan %@", NSStringFromCGPoint(point));
    
    // 獲取手指點擊的次數
//    NSLog(@"tapCount = %d", touch.tapCount);
    
//    NSLog(@"touchesBegan %p", touch);
    
    
    NSLog(@"%d", touches.count);
}
// 當手指在view上移動的時候調用
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//    UITouch *touch = [touches anyObject];
//     NSLog(@"touchesMoved %p", touch);
    
    UITouch *touch = [touches anyObject];
    // 0. 獲取上一次的位置
    CGPoint prePoint = [touch previousLocationInView:self];
//    NSLog(@"prePoint = %@", NSStringFromCGPoint(prePoint));
    
    // 1.獲取當前的位置
    CGPoint currentPoint = [touch locationInView:self];
//    NSLog(@"currentPoint = %@", NSStringFromCGPoint(currentPoint));
    
    CGFloat moveX = currentPoint.x - prePoint.x;
    CGFloat moveY = currentPoint.y - prePoint.y;
    
//    NSLog(@"moveX = %.1f", moveX);

    // 2.改變當前視圖的位置,為手指指定的位置
    CGPoint temp =  self.center;
//    NSLog(@"%f,%f",self.bounds.origin.x,self.bounds.origin.y);
    temp.x += moveX;
    temp.y += moveY;
    self.center = temp;

}
// 當手指離開view的時候調用
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//    UITouch *touch = [touches anyObject];
//    NSLog(@"touchesEnded %p", touch);
}
// 當觸摸事件被打斷的時候調用
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    
}
View Code

 

 


免責聲明!

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



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