hitTest方法與PointInside

hitTest

  • 作用:尋找最適合的View
    參數(shù):當前手指所在的點.產(chǎn)生的事件
    返回值:返回誰, 誰就是最適合的View.
    什么時候用調(diào)用:只要一個事件,傳遞給一個控件時, 就會調(diào)用這個控件的hitTest方法
    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

PointInside

  • 作用:判斷point在不在方法調(diào)用者上
    point:必須是方法調(diào)用者的坐標系
    什么時候調(diào)用:hitTest方法底層會調(diào)用這個方法,判斷點在不在控件上.
    -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
        return YES;
    }

hitTest底層實現(xiàn):

  • 1.判斷當前能不能接收事件
          if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) 
          return  nil;
  • 2.判斷觸摸點在不在當前的控件上
         if(![self pointInside:point withEvent:event]) return nil;
  • 3.從后往前遍歷自己的子控件
int count = (int)self.subviews.count;
        for (int i = count - 1; i >= 0;i-- ) {
         UIView *childV = self.subviews[i];
       // 把當前坐標系上的點轉換成子控件坐標系上的點.
        CGPoint childP = [self convertPoint:point toView:childV];
        判斷自己的子控件是不是最適合的View
        UIView *fitView = [childV hitTest:childP withEvent:event];
        如果子控件是最適拿的View,直接返回
            if (fitView) {
                return  fitView;
            }
}
  • 4.自己就是最適合的View
    return self.

練習1

  • 業(yè)務邏輯:
    底部一個按鈕, 按鈕的上面有一個View,遮擋在按鈕的上面.
    點擊View時, View接收事件,當發(fā)現(xiàn)點擊的點在按鈕的位置時, 讓底部的按鈕處理事件.

  • 實現(xiàn)思路:
    實現(xiàn)View的touchBegain方法,先監(jiān)聽UIView的點擊.
    并去實現(xiàn)UIView的HitTest方法, 在hitTest方法當中通過把當前點轉換成按鈕所在的坐標系
    CGPoint btnP = [self convertPoint:point toView:self.btn];
    轉換過后查看當前點在不在按鈕上,如果在按鈕上,就直接返回按鈕.
    如果有在按鈕上,保持系統(tǒng)默認做法.

  • 實現(xiàn)代碼:

        -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
            判斷當前點在不在按鈕上.
            把當前點轉換成按鈕所在的坐標系
            CGPoint btnP = [self convertPoint:point toView:self.btn];
            if ([self.btn pointInside:btnP withEvent:event]) {
                return self.btn;
            }else{
               return [super hitTest:point withEvent:event];
            }
        }

練習2

  • 業(yè)務邏輯:
    按鈕可以隨著手指拖動而拖動.拖動過程當中,按鈕當中的子控件也跟著拖動.
    讓超過按鈕的子控件也能夠響應事件,一般情況下,當一個控件超過他的父控件的時候,是不能夠接收事件的.
    現(xiàn)在要做的事情就讓超過父控件的按鈕也能夠響應事件.

  • 實現(xiàn)思路:

    • 先辦到讓按鈕能夠跟隨著手指移動而移動.
      實現(xiàn)按鈕的touchesMoved方法,在touchesMoved方法當中,獲得當前手指所在的點.以前上一個點.
      分別計算X軸的偏移量以及Y軸的偏移量.
      然后修改當前按鈕的transform讓按鈕辦到能夠跟隨著手指移動而移動.

    • 第二步, 實現(xiàn)按鈕的hitTest方法.
      在該方法當中去判斷當前的點在不在按鈕的子控件上.
      如果在按鈕的子控件上.就返回按鈕的子控件如果不在的話, 就保持系統(tǒng)的默認做法.

  • 實現(xiàn)代碼:
    第一步,讓按鈕能夠跟隨著手指移動而移動

        -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
            獲取當前的手指
            UITouch *touch = [touches anyObject];
            獲取當前手指所在的點
            CGPoint curP = [touch locationInView:self];
            獲取當前手指的上一個點
            CGPoint preP = [touch previousLocationInView:self];
            計算X軸的偏移量
            CGFloat offsetX = curP.x - preP.x;
            計算Y軸的偏移量
            CGFloat offsetY = curP.y - preP.y; 
            修改按鈕的形變,讓按鈕能夠移動.   
            self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);    
        }
  • 第二步,實現(xiàn)hitTest方法,判斷手指當前所在的點在不在按鈕的子控件上.
        -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
            把當前所在的點轉換成按鈕子控件上面的點
            CGPoint chatP =  [self convertPoint:point toView:self.chatBtn];
            判斷轉換后的點在不在按鈕的控件上.
            if ([self.chatBtn pointInside:chatP withEvent:event]) {如果在
                直接返回,也就意味著,當前最適合的View,就是這個按鈕
                return self.chatBtn;
            }else{如果不在,那么就保持系統(tǒng)原有做法.
              return  [super hitTest:point withEvent:event];
            }
        }
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 前言: 按照時間順序,事件的生命周期是這樣的: 事件的產(chǎn)生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vi...
    reviewThis閱讀 803評論 1 2
  • 前言 按照時間順序,事件的生命周期是這樣的: 事件的產(chǎn)生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vie...
    歡博閱讀 649評論 0 3
  • 本文來自:http://ios.jobbole.com/84081/ 前言: 按照時間順序,事件的生命周期是這樣的...
    HackerOnce閱讀 2,943評論 1 10
  • 前言: 按照時間順序,事件的生命周期是這樣的:事件的產(chǎn)生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vie...
    陽明AI閱讀 395評論 0 4
  • 文/坐看云起情深時 首先,大家都知道贊賞賬戶,是用于原創(chuàng)文章的贊賞收款用的。 現(xiàn)在的微信公眾號功能升級之后。開通贊...
    培紅說情感閱讀 2,389評論 2 8

友情鏈接更多精彩內(nèi)容