iOS Button按鈕 熱區的放大


 

 一,蘋果提出的有時候不太好用  二,運行時更改 往下看

    Apple的iOS人機交互設計指南中指出,按鈕點擊熱區應不小於44x44pt,否則這個按鈕就會讓用戶覺得“很難用”,因為明明點擊上去了,卻沒有任何響應。

但我們有時做自定義Button的時候,設計圖上的給出按鈕尺寸明顯要小於這個數。例如我之前做過的自定義Slider上的Thumb只有12x12pt,做出來后我發現自己根本點不到按鈕……

這個問題在WWDC 2012 Session 216視頻中提到了一種解決方式。它重寫了按鈕中的pointInside方法,使得按鈕熱區不夠44×44大小的先自動縮放到44×44,再判斷觸摸點是否在新的熱區內。

 

 

//官方在視頻中給出的示例源碼
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)withEvent
{
    CGFloat widthDelta = 44.0 - bounds.size.width;
    CGFloat heightDelta = 44.0 - bounds.size.height;
    bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
    return CGRectContainsPoint(bounds, point);
}

Apple的iOS人機交互設計指南中指出,按鈕點擊熱區應不小於44x44pt,否則這個按鈕就會讓用戶覺得“很難用”,因為明明點擊上去了,卻沒有任何響應。

但我們有時做自定義Button的時候,設計圖上的給出按鈕尺寸明顯要小於這個數。例如我之前做過的自定義Slider上的Thumb只有12x12pt,做出來后我發現自己根本點不到按鈕……

這個問題在WWDC 2012 Session 216視頻中提到了一種解決方式。它重寫了按鈕中的pointInside方法,使得按鈕熱區不夠44×44大小的先自動縮放到44×44,再判斷觸摸點是否在//官方在視頻中給出的示例源碼

 不過這里有兩個小問題:

  • 當定義的Button.frame大於44×44時,這里仍然會將熱區縮小至44×44,從而導致超過44×44的按鈕熱區失去響應。

  • bounds變量未定義

修正后的代碼如下:

 

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
    CGRect bounds = self.bounds;
    //若原熱區小於44x44,則放大熱區,否則保持原大小不變
	CGFloat widthDelta = MAX(44.0 - bounds.size.width, 0);
	CGFloat heightDelta = MAX(44.0 - bounds.size.height, 0);
	bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
	return CGRectContainsPoint(bounds, point);
}

 

二: 運行時模式  UIButton+LP  

//  UIButton+LP.h

 

#import <UIKit/UIKit.h>

 @interface UIButton (LP)

@property(nonatomic,assign)CGFloat enlargedEdge;

//-(void)setEnlargedEdge:(CGFloat)enlargedEdge;

//-(float)enlargeEdge;

-(void)setEnlargedEdgeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right;

@end

 

//  UIButton+LP.m

#import "UIButton+LP.h"

#import <objc/runtime.h>

 

@implementation UIButton (LP)

staticchar topEdgeKey;

staticchar leftEdgeKey;

staticchar bottomEdgeKey;

staticchar rightEdgeKey;

 

-(void)setEnlargedEdge:(CGFloat)enlargedEdge

{

    [selfsetEnlargedEdgeWithTop:enlargedEdge left:enlargedEdge bottom:enlargedEdge right:enlargedEdge];

}

 

-(float)enlargeEdge

{

    return [(NSNumber *)objc_getAssociatedObject(self, &topEdgeKey) floatValue];

}

 

-(void)setEnlargedEdgeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right

{

    objc_setAssociatedObject(self, &topEdgeKey, [NSNumbernumberWithFloat:top], OBJC_ASSOCIATION_RETAIN_NONATOMIC);

     objc_setAssociatedObject(self, &leftEdgeKey, [NSNumbernumberWithFloat:left], OBJC_ASSOCIATION_RETAIN_NONATOMIC);

     objc_setAssociatedObject(self, &bottomEdgeKey, [NSNumbernumberWithFloat:bottom], OBJC_ASSOCIATION_RETAIN_NONATOMIC);

     objc_setAssociatedObject(self, &rightEdgeKey, [NSNumbernumberWithFloat:right], OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

 

-(CGRect)enlargedRect

{

    NSNumber * topEdge = objc_getAssociatedObject(self, &topEdgeKey);

    NSNumber * leftEdge = objc_getAssociatedObject(self, &leftEdgeKey);

    NSNumber * bottomEdge = objc_getAssociatedObject(self, &bottomEdgeKey);

    NSNumber * rightEdge = objc_getAssociatedObject(self, &rightEdgeKey);

    if(topEdge && leftEdge && bottomEdge && rightEdge){

        CGRect enlargedRect = CGRectMake(self.bounds.origin.x - leftEdge.floatValue, self.bounds.origin.y - topEdge.floatValue, self.bounds.size.width + rightEdge.floatValue + leftEdge.floatValue ,self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);

        return enlargedRect;

    }else{

        returnself.bounds;

    }

}

 

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

{

    if(self.alpha <= 0.01 || !self.userInteractionEnabled ||self.hidden){

        returnnil;

    }

    CGRect enlargedRect = [selfenlargedRect];

    returnCGRectContainsPoint(enlargedRect, point)?self:nil;

}

@end

 


免責聲明!

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



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