1.系統(tǒng)是如何判斷控件狀態(tài)的
在UIControl中有這個方法
- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents;
用它來發(fā)送控件狀態(tài)。
什么時候發(fā)送對應(yīng)狀態(tài)胰挑,我們可以自己來進(jìn)行來判斷士袄。
這要用到以下幾個UIResponder中的方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- 在touchesBegan時隔崎,要發(fā)送UIControlEventTouchDown事件圣絮。
- 在touchesMoved中,根據(jù)前一刻point和當(dāng)前時刻的point钱贯,來判斷發(fā)送UIControlEventTouchDragInside吹截,UIControlEventTouchDragOutside,UIControlEventTouchDragEnter或UIControlEventTouchDragExit事件鳖谈。
- 在touchesEnded的時岁疼,應(yīng)該發(fā)送UIControlEventTouchUpInside或UIControlEventTouchUpOutside事件。
- 在touchesCancelled時缆娃,要發(fā)送UIControlEventTouchCancel捷绒。
控件highlighted只要直接賦值YES 或 NO 就可以了。
- 在touchesBegan時 highlighted為YES
- 在touchesEnded和touchesCancelled時 highlighted應(yīng)該為NO贯要。
- 在touchesMoved中暖侨,要判斷觸碰的位置來設(shè)置highlighted的值。
2.如何判斷觸碰的位置
在UITouch中有以下兩個方法崇渗。
- (CGPoint)locationInView:(nullable UIView*)view;//獲得當(dāng)前觸摸點的point
- (CGPoint)previousLocationInView:(nullable UIView *)view;//獲得先前觸摸點的point
結(jié)合CoreGraphics中的 bool CGRectContainsPoint(CGRect rect, CGPoint point)
方法來判斷觸碰點與控件的關(guān)系
以touchesEnded和touchesMoved為例字逗。
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.highlighted = NO;
CGPoint point = [touches.anyObject locationInView:self];
if (CGRectContainsPoint(self.bounds, point)) { //判斷point是否在self.bounds內(nèi)。
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
} else {
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = touches.anyObject;
BOOL currentInside = CGRectContainsPoint(self.bounds, [touch locationInView:self]);
BOOL preInside = CGRectContainsPoint(self.bounds, [touch previousLocationInView:self]);
if (currentInside) {
self.highlighted = YES;
if (preInside) {
[self sendActionsForControlEvents:UIControlEventTouchDragInside];
} else {
[self sendActionsForControlEvents:UIControlEventTouchDragEnter];
}
} else {
self.highlighted = NO;
if (preInside) {
[self sendActionsForControlEvents:UIControlEventTouchDragExit];
} else {
[self sendActionsForControlEvents:UIControlEventTouchDragOutside];
}
}
}
以上這些宅广,其實可以讓系統(tǒng)來做扳肛,只要調(diào)用即可。
[super touchesXXX:touches withEvent:event]
例如:
以下代碼就等于上面的一大段的touchesMoved方法了乘碑。
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
}
3.系統(tǒng)的方法如此簡便挖息,那為什么我們還要重寫touches系列的方法
因為系統(tǒng)的touchesMoved在手指移動時,大概是離開控件70pt左右內(nèi)兽肤,控件仍然會處于高亮的狀態(tài)套腹,這時touchesEnded則會觸發(fā)UIControlEventTouchUpInside事件。
現(xiàn)實中资铡,我們會遇到許多奇奇怪怪的需求电禀,系統(tǒng)原本的方法不足以滿足需求,這就需要我們自己來重寫方法了笤休。
去研究尖飞,探索系統(tǒng)的方法是如何實現(xiàn)的,最終學(xué)會創(chuàng)新,這是件非常有趣的事政基。