处理单个UITabBarItem的长按

8

我在选项卡栏上使用长按手势。但我只需要在特定的选项卡上使用长按手势。

我该如何解决这个问题?我能够自定义选项卡中的长按手势吗?


请分享您的代码或IB。 - Kaushil Ruparelia
我没有用正确的代码开始。 - erb dinesh
5个回答

13

以下是我使用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
        }
    }
}

"if let vc = nc.viewControllers.first as? MyTabControllerProtocol",其中MyTabControllerProtocol是连接到应用程序选项卡的任何控制器,并针对该命令进行定位。请使用您自己的控制器替换MyTabControllerProtocol。 - Jan Bergström

7
您可以创建UITabBarController的子类,并在其tabBar上添加一个UILongPressGestureRecognizer。作为手势识别器的代理,您可以选择性地控制何时检测长按手势。由于选项卡项目将在用户触摸它时被选中,您可以使用selectedItem属性进行此检查。
@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

4
能否在不切换选项卡的情况下识别TabBarItem的长按操作? - Akhil K C
如果用户选择了第一个项目,然后在任何其他项目上进行了轻触并按住,它仍然可以工作,这并不好。因为第一个项目仍然会被选中! - Yaroslav Dukal
@AkhilKC,请查看UITabBarControllerDelegate中的shouldSelect方法。 - Jan Erik Schlorf

3

这里是 Swift 5 的解决方案: 通过 storyboard 或代码给“整个”选项卡栏添加长按手势识别器。 不要忘记让您的 ViewController 成为它的代理,并实现以下代理方法,以检查传入的触摸是否位于您的选项卡栏子视图中的任一视图中。如果是,则返回 true,否则返回 false。 下面是代码,将使识别器仅在我们长按第一个选项卡时触发:

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

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



}

注意:tabbar.subviews数组的计数为项数加1,其中包括tabbar的背景。因此,如果您想获取第一项的视图,可以使用索引1而不是0。

谢谢,这是最好的答案。 - Aleksandr Honcharov

2
我通过获取用户可以交互的特定tabBarItem的视图,并向其添加长按手势来实现这一点。通过这种方式,您无需编写任何协议或子类化TabBarViewController。
let longPressGestureRecognizer = UILongPressGestureRecognizer.init(target: self, action: #selector(longTap(_:)))
    longPressGestureRecognizer.minimumPressDuration = 1.0
    self.tabBarController?.orderedTabBarItemViews()[0].addGestureRecognizer(longPressGestureRecognizer)

关于获取tabBarItemViews:

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

备注: 视图控制器即“self”是选项卡控制器中的第一个项目。


1
如果您只需要识别 tabBar 项中的长按操作,可以在相应的 viewController 的 viewDidLoad 方法中执行以下操作:
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector(handleLongPress:)];
[self.tabBarController.tabBar addGestureRecognizer: longPressGesture];

然后:

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

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

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

如果您仅切换选项卡,这将不会触发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接