Reputation: 4119
I'd like to begin animating a UITabBarItem
when the user touches down on the tab. However, UITabBarDelegate
only provides a didSelect
method. What's the best way of detecting a UIControlEvents.touchDown
event in this context?
Upvotes: 3
Views: 358
Reputation: 74
You subclass UITabBar
and override hitTest:withEvent:
Here's an example of a subclass that slightly scales down the image upon touch-down, then restores it upon touch-up-inside
@interface TRCTabBar : UITabBar
@end
@implementation TRCTabBar
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if ([view isKindOfClass:UIControl.class]) {
CGFloat scale = 0.90;
CGAffineTransform t = CGAffineTransformScale(CGAffineTransformIdentity, scale, scale);
[UIView animateWithDuration:0.14 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
view.transform = t;
} completion:nil];
}
return view;
}
// used as a signal to restore the image back to its original state
- (void)setSelectedItem:(UITabBarItem *)selectedItem {
[super setSelectedItem:selectedItem];
for (UIView *view in self.subviews) {
if (!CGAffineTransformIsIdentity(view.transform)) {
view.transform = CGAffineTransformIdentity;
}
}
}
@end
Some notes:
Unlike the touch-down event that's accessed via hitTest:withEvent:
, the touch-up-inside event isn't accessed directly; Simply override setSelectedItem:
to have a chance to perform some actions when the user lifts their finger.
There's no way to monitor a touch-up-outside (or any other cancellation event, for this matter). So if a user taps, then drags outside, then lifts their finger, the image remains scaled down until next setSelectedItem:
is called.
If you use animations (like in my provided example code), you must use the UIViewAnimationOptionAllowUserInteraction
option. Otherwise setSelectedItem:
isn't always called.
You only want to pick up touches from the UITabBarButton
class (that's the control that responds to the touch-down event). A user may also accidentally touch the UITabBar
itself, and you should ignore this touch. UITabBarButton
is an internal UIKit class, but it's a subclass of UIControl
. Use that to filter out all other ignored UIView
s (like the UITabBar
itself).
Obviously, make sure to set your UITabBar
's class (in Interface Builder or programatically) as your custom class.
Upvotes: 1