1

我的 iPad 应用程序主屏幕顶部有一个 UIToolbar。它上面有 6 个 UIBarButtonItems。其中 4 个项目触发 UIPopOvers 出现。其他 2 个项目要么切换到不同的视图,要么更改当前视图的某些内容。

4 个 UIPopOver 中的 3 个从轻按的 UIBarButtonItem 中出现,第 4 个出现在屏幕中间,没有箭头。

我想要以下功能,但很难使用它:

  1. 当没有显示 UIPopOver 并且用户点击生成 UIPopOver 的 UIBarButtonItems 之一时,显示 UIPopOver(很简单;让它工作。)
  2. 当显示 UIPopOver 并且用户点击 UIToolbar 时,关闭该 UIPopOver。(使用需要点击 1 次的 UIGestureRecognizer 来完成这项工作。)
  3. 当显示 UIPopOver 并且用户点击 UIBarButtonItem 到哪个 UIPopOver 被“绑定”时,关闭 UIPopOver。(这是我的问题。)
  4. 当显示 UIPopOver 并且用户点击另一个 UIBarButtonItem 时,关闭当前 UIPopOver 并显示适当的新 UIPopOver。(这工作正常。)

所以,我面临的问题是 UIGestureRecognizer 在按钮点击之前触发。当用户按下 UIBarButtonItem 时,我也找不到“选择退出” UIGestureRecognizer 的好方法(因此,只有在点击 UIToolbar 本身时才触发 UIGestureRecognizer 的操作,而不是 UIBarButtonItem)。这样做的最终结果是,当显示 UIPopOver(来自 UIBarButtonItem)并且用户点击相同的 UIBarButtonItem 时,UIPopOver 被解除,然后再次显示。

我试图避免某种时间问题,我将“toolbarTapped”标志设置为 YES 0.10 秒,然后将其设置回 NO(或类似的东西)。

我想找到一种方法来真正优雅地做到这一点(而不是 hack-y)。

我似乎无法找到一种方法来确定何时基于 UIBarButtonItem 触摸触发 UIGestureRecognizer,因为 UIGestureRecognizer 首先触发并且似乎没有一种好的(非私有)方法来获取 UIBarButtonItem 的框架。

基本上,我正在尝试使 UIToolbar 及其 UIBarButtonItems 的行为符合任何合理的人所期望的方式,但我正在把头撞到墙上。

这是 UIGestureRecognizer 的代码:

// Initialization
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(removeAllPopOvers)];
[tapRecognizer setCancelsTouchesInView:NO];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
[[self Toolbar] addGestureRecognizer:tapRecognizer];

// Tap handler
- (void)removeAllPopOvers {
    NSLog(@"removing all popovers");
    if ([self firstPopOver]) {
        [[self firstPopOver] dismissPopoverAnimated:YES];
        [self setFirstPopOver:nil];
    }
    // and so on with the rest...
}

这是我的 UIPopOver 之一的显示方式:

- (IBAction)showSettings:(id)sender {
    NSLog(@"settings button tapped");
    if (![self SettingsPopOver]) {
        SettingsViewController *settingsVC = [[SettingsViewController alloc] initWithNibName:@"SettingsView-iPad" bundle:nil];
        UIPopoverController *popOver = [[UIPopoverController alloc] initWithContentViewController:settingsVC];
        [popOver setDelegate:self];
        [self setSettingsPopOver:popOver];
        [[self SettingsPopOver] setPopoverContentSize:CGSizeMake(320, 300)];
        [[self SettingsPopOver] presentPopoverFromBarButtonItem:[self Settings] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    }
}

所有这一切的最终结果是我可以选择以下两个选项之一(但不能同时选择两者):

  1. 允许 UIBarButtonItem 关闭 UIPopOver。
  2. 允许点击 UIToolbar 以关闭 UIPopOver。

有任何想法吗?

谢谢!

4

3 回答 3

0

对于问题 3:

if ([self.popoverController isPopoverVisible])
    [self.popoverController dismissPopoverAnimated:YES];
else

如果弹出框可见,它将关闭它;否则你创建弹出框。

其余的,如果触摸工具栏,您是否只希望弹出框关闭?如果用户触摸屏幕上的其他任何地方,您希望弹出框保留吗?

弹出框控制器有passthroughViews一个属性,我相信它允许您向其添加 uiview,因此实际上如果您添加主视图并对其进行触摸,它不会触发弹出框关闭。我不完全确定这是如何工作的,您需要进行一些挖掘。

https://developer.apple.com/library/ios/#documentation/uikit/reference/UIPopoverController_class/Reference/Reference.html

于 2012-02-24T17:46:11.523 回答
0

目前,我已经实现了一些可行的东西,但并不优雅(至少,我认为不是)。

基本上,我所做的是通过首先将 UIGestureRecognizer 发送到“缓冲区”方法来延迟操作:

#pragma mark - PopOver Dismissal
// dismissAllPopOversBuffer is called as the action of my UIGestureRecognizer
- (void)dismissAllPopOversBuffer {
    NSLog(@"dismiss all popovers buffer...");
    [self performSelector:@selector(dismissAllPopOvers) withObject:nil afterDelay:0.1];
}
- (void)dismissAllPopOvers {
    NSLog(@"dismissing all popovers");
    // actual dismissal logic
}

如您所见,这将实际解除逻辑推迟了 0.1 秒。然后,在每个按钮按下方法中,我这样做:

#pragma mark - UIBarButtonItem Press Event Handlers
- (IBAction)buttonPressed:(id)sender {
    [NSObject cancelPreviousPerformRequestsWithTarget:self
                                             selector:@selector(dismissAllPopOvers)
                                               object:nil];
    // The rest of the logic to dismiss/show UIPopOver
}

到目前为止,我的测试表明它可以工作。根据 NSLog 时间戳,UIGestureRecognizer 操作和 UIBarButtonItem 事件之间的实际经过时间通常为 1 毫秒(0.001 秒),因此推出 0.1 秒(或正常时间间隔的 100 倍)在大多数情况下应该是安全的,但我仍然不喜欢。

我很想找到一种方法来确定用户何时点击了 UIToolbar 而不是任何 UIBarButtonItems。这看起来相当简单(逻辑上)但相当困难(实际上)。

于 2012-02-24T17:12:15.323 回答
0

所以我解决了通过实现手势识别器委托然后调用下面的方法来同时识别2个手势(对我来说,这允许我的平移手势滚动和滑动手势调用一个新视图以同时弹出注册时间):

(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer      
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
  return YES;
}
于 2015-03-20T21:13:58.927 回答