iOS之?dāng)U大UIButton(UIView)的點擊范圍

前言

UI給的圖有時候很小,或者有個需求需要我們擴大button的點擊區(qū)域

我們一般的操作是在button 上添加一個view 增加點擊事件,但是我們還有其他更方便的方法去擴大button 的點擊區(qū)域。

思考

怎樣來實現(xiàn)這個功能呢?又有多少種方式可以實現(xiàn)呢?下面一一來講。

  • 理解事件傳遞過程,用這個來實現(xiàn)擴大點擊范圍
  • 使用Runtime機制擴大點擊范圍

時間傳遞過程

當(dāng)用戶點擊屏幕后:

  1. UIApplication 先響應(yīng)事件。

  2. 然后傳遞給UIWindow。

  3. 如果window可以響應(yīng)。就開始遍歷window的subviews。遍歷原則是:從離用戶最近的那個子視圖去遍歷

  4. 遍歷的過程中,如果第一個遍歷的view1可以響應(yīng),那就遍歷這個view1的subviews(依次這樣不停地查找,直至查找到合適的響應(yīng)事件view)。

  5. 如果view1不可以響應(yīng),那就開始對view2進(jìn)行判斷和子視圖的遍歷。依次類推view3,view4……

  6. 如果最后沒有找到合適的響應(yīng)view,這個消息就會被拋棄。這個就是iOS中的事件鏈。

如下圖所示:

事件傳遞過程.png

然而事件的響應(yīng)鏈條是事件鏈條的逆向,根據(jù)視圖層級的添加順序從后往前的

擴大UIButton范圍關(guān)鍵的兩個方法:UIView方法

// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;

// default returns YES if point is in bounds
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;

第一種方法

繼承與UIButton,重寫下面的方法:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
    CGRect bounds = self.bounds;
    //擴大原熱區(qū)直徑至26,可以暴露個接口,用來設(shè)置需要擴大的半徑。
    CGFloat widthDelta = 26;
    CGFloat heightDelta = 26;
    bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
    return CGRectContainsPoint(bounds, point);
}

第二種:重寫方法 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    CGRect rectRange = CGRectInset(self.bounds, -30.0, -30.0);
    
    if (CGRectContainsPoint(rectRange, point)) {
        return self;
    }else{
        return nil;
    }
    
    return self;
}

其實我們上面所做的變化其實如果仔細(xì)看點擊區(qū)域還是個矩形,如果需要我們將點擊區(qū)域規(guī)定在圓形范圍 內(nèi),我們可以這樣做:

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    [super hitTest:point withEvent:event];
    
    CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
    
    
   //當(dāng)然這個半徑也可以擴大
    CGFloat raidus = self.frame.size.height >= self.frame.size.width ?self.frame.size.width/2 :self.frame.size.width/2;
    
   //傳入中心點 實時點擊點 與半徑判斷 點擊點是否在半徑區(qū)域內(nèi)
    BOOL pointInRound =[self touchPointInsideCircle:center radius:raidus targetPoint:point];
    
    if (pointInRound) {
        return self;
    }else
    {
        return nil;
    }
}

//用來判斷 圓形點擊區(qū)域
- (BOOL)touchPointInsideCircle:(CGPoint)center radius:(CGFloat)radius targetPoint:(CGPoint)point {
    CGFloat dist = sqrtf((point.x - center.x) * (point.x - center.x) +
                         (point.y - center.y) * (point.y - center.y));
    return (dist <= radius);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 重點參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,700評論 0 15
  • 初識iOS APP開發(fā)#### 在iOS APP開發(fā)中, main函數(shù)仍是程序的入口和出口, 但main函數(shù)不需要...
    DeanYan閱讀 6,609評論 0 3
  • 怎樣來實現(xiàn)這個功能呢?又有多少種方式可以實現(xiàn)呢?下面一一來講。 理解事件傳遞過程,用這個來實現(xiàn)擴大點擊范圍使用Ru...
    karven閱讀 7,493評論 2 59
  • 概述 iOS響應(yīng)者鏈(Responder Chain)是支撐App界面交互的重要基礎(chǔ),點擊、滑動、旋轉(zhuǎn)、搖晃等都離...
    嚕嚕嚕嚕嚕嚕嚕嚕閱讀 771評論 0 6
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件。本想自己總結(jié)一下,但是遇到了這篇文章,感覺總結(jié)的已經(jīng)很到位,特此轉(zhuǎn)載。作者:L...
    WQ_UESTC閱讀 6,237評論 4 26

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