UIControl是App开发中每天都需要使用,每一个IOS开发者对于UIControl都是无比熟悉的,UIButton、UISlider、UISwitch等等。 而我们使用这些控件的主要方式就是通过UIControl提供给我们的`Control Event` ``` enum { UIControlEventTouchDown = 1 << 0, UIControlEventTouchDownRepeat = 1 << 1, UIControlEventTouchDragInside = 1 << 2, UIControlEventTouchDragOutside = 1 << 3, UIControlEventTouchDragEnter = 1 << 4, UIControlEventTouchDragExit = 1 << 5, UIControlEventTouchUpInside = 1 << 6, UIControlEventTouchUpOutside = 1 << 7, UIControlEventTouchCancel = 1 << 8, UIControlEventValueChanged = 1 << 12, UIControlEventEditingDidBegin = 1 << 16, UIControlEventEditingChanged = 1 << 17, UIControlEventEditingDidEnd = 1 << 18, UIControlEventEditingDidEndOnExit = 1 << 19, UIControlEventAllTouchEvents = 0x00000FFF, UIControlEventAllEditingEvents = 0x000F0000, UIControlEventApplicationReserved = 0x0F000000, UIControlEventSystemReserved = 0xF0000000, UIControlEventAllEvents = 0xFFFFFFFF }; ``` 这些control event对于我们来说也不太陌生,正是由这些简单的event拼凑成了我们应用的交互。 不过这里面却是有一个小秘密。 ##小秘密——70像素 小秘密是什么呢? 如果你用过`UIControlEventTouchDragExit` 并且你对于`UIControlEventTouchDragExit`的触摸时机较为敏感的话,你就会发现如果手指离开我们的Control的bounds的那一刻,`UIControlEventTouchDragExit`并没有被触发? 可是苹果的文档写写相当清楚,当手指离开了bounds的时候就应该触发。 ``` UIControlEventTouchDragExit An event where a finger is dragged from within a control to outside its bounds. Available in iOS 2.0 and later. Declared in UIControl.h. ``` 事实是检验真理的唯一标准? 所以我试着输出了一下`UIControlEventTouchDragExit`被触发时候touch的坐标。 结果就是`70像素左右`,每次触发时候的位置都是距离control的边界70像素左右 可能文字描述的不够形象。放张图
图中的红色边框就是一个按钮的bounds 而图中的绿色边框就是事件触发时候的区域边界 当手指越过绿色边框的时候,事件就被触发了 而红色边框和绿色边框之间的距离是`70像素` 那是不是其他的contrl event是不是符合这个规律呢? 我做了简单的测试,发现是的 `UIControlEventTouchDragInside`、`UIControlEventTouchDragOutside`等等的触发边界都是70像素左右。 ##自定义触发边界 不得不说,有时候这多出来的70像素是相当的讨厌的,因为我们不需要,那么我们是否能够去自定义呢? 答案当然是肯定的。 还是以`UIControlEventTouchDragExit`为例吧,让我们来修改`UIControlEventTouchDragExit`的触发边界 贴出一段代码 ``` - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { // 设置新的边界 CGFloat boundsExtension = 25.0f; CGRect outerBounds = CGRectInset(self.bounds, -1 * boundsExtension, -1 * boundsExtension); // 判断触摸位置 BOOL touchOutside = !CGRectContainsPoint(outerBounds, [touch locationInView:self]); if(touchOutside) { // 判断是UIControlEventTouchDragExit/UIControlEventTouchDragOutside BOOL previousTouchInside = CGRectContainsPoint(outerBounds, [touch previousLocationInView:self]); if(previousTouchInside) { [self sendActionsForControlEvents:UIControlEventTouchDragExit]; } else { [self sendActionsForControlEvents:UIControlEventTouchDragOutside]; } } // 如果不是想要修改的control event,返回原操作 return [super continueTrackingWithTouch:touch withEvent:event]; } ``` ##感想 虽然自己也每天使用UIControl,不过也是现在才发现这个有趣的现象,IOS中还是有很多东西需要探索,每日自省自勉。