Handle long press on a single UITabBarItem
Asked Answered
L

5

8

I use the long press gesture on a tab bar. But I only need the long press gesture for one particular tab bar item.

How can I solve this problem? Could I customize the long press gesture in tab bar?

Lupelupee answered 6/10, 2015 at 11:13 Comment(2)
Please share your code or IB.Remitter
i didn't start with correct code.Lupelupee
L
7

You can subclass UITabBarController and add a UILongPressGestureRecognizer to it's tabBar. Acting as the delegate of the gesture recognizer will allow you to be selective over when it will detect a long press. Since the tab bar item will be selected as soon as the user touches it you can use the selectedItem property to perform this check.

@interface TabBarController () <UIGestureRecognizerDelegate>
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressRecognizer;

@end

@implementation TabBarController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(recognizerFired:)];
    self.longPressRecognizer.delegate = self;
    [self.tabBar addGestureRecognizer:self.longPressRecognizer];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

    // This will ensure the long press only occurs for the
    // tab bar item which has it's tag set to 1.
    // You can set this in Interface Builder or in code
    // wherever you are creating your tabs.
    if (self.tabBar.selectedItem.tag == 1) {
        return YES;
    }
    else {
        return NO;
    }

}

- (void)recognizerFired:(UILongPressGestureRecognizer *)recognizer {
    // Handle the long press...
}

@end
Laboratory answered 6/10, 2015 at 12:18 Comment(3)
Is it possibe to recognize long press on TabBarItem without switching tab?Doggy
What if user selected first item then tapped and hold on any other item it will still work, which is not cool . Because first item would be still selected !Cosmogony
@AkhilKC take a look at the shouldSelect method from UITabBarControllerDelegateDextral
F
13

Here's how I did it using Swift 3:

protocol MyTabControllerProtocol: class {
    func tabLongPressed()
}

class MyTabController: UITabBarController {
    func viewDidLoad() {
        super.viewDidLoad()

        viewControllers = [
            // add your view controllers for each tab bar item
            // NOTE: if you want view controller to respond to long press, then it should extend MyTabControllerProtocol
        ]

        let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(astroButtonItemLongPressed(_:)))
        tabBar.addGestureRecognizer(longPressRecognizer)
    }

    func astroButtonItemLongPressed(_ recognizer: UILongPressGestureRecognizer) {
        guard recognizer.state == .began else { return }
        guard let tabBar = recognizer.view as? UITabBar else { return }
        guard let tabBarItems = tabBar.items else { return }
        guard let viewControllers = viewControllers else { return }
        guard tabBarItems.count == viewControllers.count else { return }

        let loc = recognizer.location(in: tabBar)

        for (index, item) in tabBarItems.enumerated() {
            guard let view = item.value(forKey: "view") as? UIView else { continue }
            guard view.frame.contains(loc) else { continue }

            if let nc = viewControllers[index] as? UINavigationController {
                if let vc = nc.viewControllers.first as? MyTabControllerProtocol {
                    vc.tabLongPressed()
                }
            } else if let vc = viewControllers[index] as? MyTabControllerProtocol {
                vc.tabLongPressed()
            }

            break
        }
    }
}
Foetid answered 13/9, 2017 at 20:11 Comment(1)
The "if let vc = nc.viewControllers.first as? MyTabControllerProtocol" where MyTabControllerProtocol is any controller connected to the Tabs of your app with the command it is targeting. Replace MyTabControllerProtocol with yours.Rain
L
7

You can subclass UITabBarController and add a UILongPressGestureRecognizer to it's tabBar. Acting as the delegate of the gesture recognizer will allow you to be selective over when it will detect a long press. Since the tab bar item will be selected as soon as the user touches it you can use the selectedItem property to perform this check.

@interface TabBarController () <UIGestureRecognizerDelegate>
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressRecognizer;

@end

@implementation TabBarController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(recognizerFired:)];
    self.longPressRecognizer.delegate = self;
    [self.tabBar addGestureRecognizer:self.longPressRecognizer];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

    // This will ensure the long press only occurs for the
    // tab bar item which has it's tag set to 1.
    // You can set this in Interface Builder or in code
    // wherever you are creating your tabs.
    if (self.tabBar.selectedItem.tag == 1) {
        return YES;
    }
    else {
        return NO;
    }

}

- (void)recognizerFired:(UILongPressGestureRecognizer *)recognizer {
    // Handle the long press...
}

@end
Laboratory answered 6/10, 2015 at 12:18 Comment(3)
Is it possibe to recognize long press on TabBarItem without switching tab?Doggy
What if user selected first item then tapped and hold on any other item it will still work, which is not cool . Because first item would be still selected !Cosmogony
@AkhilKC take a look at the shouldSelect method from UITabBarControllerDelegateDextral
N
3

Here is a solution in swift 5 : Add longpress Gesture recognizer to the "Entire" tabbar using storyboard or code.. and Don't forget to let your ViewController be its delegate .. and implement the delegate method below to check if the incoming touch is inside "one" of your tabbar subViews .. if yes return true ,, else return false .. here are the code that will let the recognizer fire only when we longPress on the first tab:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {

    if touch.view?.isDescendant(of: tabBar.subviews[1]) == true {return true}
    return false



}

Note: tabbar.subviews array count is number of the items + 1 which is the background of the tabbar .. so if you want the view of the first item you can fint it and index 1 not 0

Nationalism answered 10/5, 2020 at 19:28 Comment(1)
Thanks, that's the best answer.Monoploid
H
2

I did this by getting the specific tabBarItem's view that user can interact and simply added the long press gesture to that. With that way you do not have to write any protocols or subclass the TabBarViewController.

let longPressGestureRecognizer = UILongPressGestureRecognizer.init(target: self, action: #selector(longTap(_:)))
    longPressGestureRecognizer.minimumPressDuration = 1.0
    self.tabBarController?.orderedTabBarItemViews()[0].addGestureRecognizer(longPressGestureRecognizer)

And as for getting the tabBarItemViews :

extension UITabBarController {
func orderedTabBarItemViews() -> [UIView] {
    let interactionViews = tabBar.subviews.filter({$0.isUserInteractionEnabled})
    return interactionViews.sorted(by: {$0.frame.minX < $1.frame.minX})
}

P.S. : The viewController, namely "self" is the first item for the tabBarController.

Hap answered 30/12, 2018 at 13:20 Comment(0)
D
1

If you just need to recognize a long press on one of the tabBar items, you can do this in the corresponding viewController's viewDidLoad method:

UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector(handleLongPress:)];
[self.tabBarController.tabBar addGestureRecognizer: longPressGesture];

And then:

- (void)handleLongPress:(UILongPressGestureRecognizer *) recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {

        UITabBar *tabBar = ((UITabBar* )recognizer.view);

        if (tabBar.selectedItem == self.tabBarItem) {
            doSomethingVeryExciting();
        }
    }
}

This won't fire if you just switch tabs.

Devy answered 9/1, 2017 at 20:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.