iOS - PopOver演示和解雇

时间:2012-02-24 14:54:44

标签: ios uigesturerecognizer uitoolbar uipopover

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

4个UIPopOvers中的3个出现在点击的UIBarButtonItem中,第4个出现在屏幕中间没有箭头。

我想要以下功能,但很难实现:

  1. 当没有显示UIPopOvers并且用户点击其中一个生成UIPopOver的UIBarButtonItem时,显示UIPopOver(非常简单;让它工作。)
  2. 当显示UIPopOver并且用户点击UIToolbar时,请关闭该UIPopOver。 (使用UIGestureRecognizer进行操作需要1次点击。)
  3. 当显示UIPopOver并且用户点击UIBopButtonItem为“TIED”的UIBarButtonItem时,关闭UIPopOver。 (这是我的问题。)
  4. 当显示UIPopOver并且用户点击另一个UIBarButtonItem时,关闭当前的UIPopOver并显示相应的新UIPopOver。 (这很好用。)
  5. 所以,我面临的问题是UIGestureRecognizer在按钮点击之前触发。当用户按下UIBarButtonItem时,我也找不到“退出”UIGestureRecognizer的好方法(因此,只有在点击UIToolbar本身而不是UIBarButtonItem时才触发UIGestureRecognizer的动作)。最终结果是,当显示UIPopOver(来自UIBarButtonItem),并且用户点击相同的UIBarButtonItem时,UIPopOver被解除,然后再次显示。

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

    我想找到一种方法来真正做到这一点(而不是黑客)。

    我似乎无法找到一种方法来确定何时基于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...
    }
    

    以下是我的一个UIPopOvers的显示方式:

    - (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。
    3. 有什么想法吗?

      谢谢!

3 个答案:

答案 0 :(得分: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。这似乎相当简单(逻辑上)但相当困难(实际上)。

答案 1 :(得分:0)

问题3的

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

如果弹出窗口是可见的,它将会忽略它;否则你会创建popover。

对于其余部分,你是否只想要在触摸工具栏时忽略弹出框?如果用户触摸屏幕上的任何其他位置,您希望弹出窗口停留吗?

popover控制器有一个passthroughViews本身我相信允许你添加一个uiview,所以如果你添加一个主视图并触及它,它将不会触发popover dismiss。我不完全确定这是如何工作的,你需要做一些挖掘。

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

答案 2 :(得分:0)

所以我通过实现Gesture Recognizer委托,然后调用下面的方法解决了同时识别2个手势的问题(对我而言,这允许我的摇动手势进行滚动和滑动手势来调用新视图以弹出注册在同一时间):

(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer      
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
  return YES;
}