3

我正在使用拆分视图模板创建一个简单的拆分视图,当然,它在纵向模式下有一个弹出框。我正在使用模板生成的默认代码,该代码添加/删除工具栏项并设置弹出框控制器并将其删除。这两个方法是 splitViewController:willShowViewController:... 和 splitViewController:willHideViewController:...

我试图弄清楚如果用户在显示弹出框时点击工具栏按钮,如何使弹出框消失。如果您点击弹出框之外的任何位置,您可以在不选择项目的情况下使弹出框消失,但如果用户再次点击该按钮,我也想让它消失。

我被困的地方是:似乎没有一种明显、简单的方法来挂钩工具栏按钮的操作。我可以知道,使用调试器,在按钮上调用的操作是 showMasterInPopover。我承认,我不熟悉以编程方式使用选择器。

我可以以某种方式编写一个动作并将其设置在工具栏项上而不覆盖已经存在的动作吗?例如,添加一个调用现在存在的动作的动作?或者我是否必须自己编写一个显示/隐藏弹出框的操作(现在可能由拆分视图控制器在幕后完成的行为???)。

还是我错过了一种简单的方法来将此行为添加到此按钮而不更改为我设置的现有行为?

谢谢!

4

6 回答 6

6

所以事实证明,通过实现 SplitViewController willPresentViewController 方法,您可以在单击 barButtonItem 时关闭弹出框,如下所示:

- (void) splitViewController:(UISplitViewController *)svc 
           popoverController: (UIPopoverController *)pc
   willPresentViewController: (UIViewController *)aViewController
{
    if (pc != nil) {
        [pc dismissPopoverAnimated:YES];
    }
}
于 2010-04-23T21:44:58.220 回答
1

因此, barButtonItem 将以 UISplitViewController 作为目标,将 showMasterInPopover: 作为动作。我在文档中找不到它,所以我有点担心不能调用它,但我通过将目标更改为 self (视图控制器)并将操作更改为自定义方法来让它工作,比如这个:

- (void)showMasterInPopover:(id)sender {
    // ...insert custom stuff here...
    [splitViewController showMasterInPopover:sender];
}
于 2010-04-14T20:44:40.650 回答
0

没有代表发表真正的评论。:-(

@Jann - 我很确定伊丽莎白想要做的是非常标准的。例如,当您按下左上角的工具栏按钮时,预装在 iPad 上的 Notes 应用程序会关闭并打开弹出框。

于 2010-04-17T15:28:09.137 回答
0

也许你们只是把它复杂化了太多,或者我读到的东西与你们想要做的完全不同……但也许,这就是你们所有人都想弄清楚的:

-(void)togglePopOverController {

if ([popOverController isPopoverVisible]) {

[popOverController dismissPopoverAnimated:YES];

} else {

[popOverController presentPopoverFromBarButtonItem:bbiOpenPopOver permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

}

}
于 2010-05-11T18:57:25.000 回答
0

下面是我的解决方案。它开始类似于 greenisus 的解决方案,通过挂钩UISplitViewController的工具栏按钮事件处理程序。我在控制器中使用一个标志来跟踪弹出框是否打开。最后,为了处理用户打开弹出框,然后通过单击弹出框外部将其关闭的情况,我实现了UIPopoverControllerDelegate协议。

一、控制器接口:

@interface LaunchScene : NSObject <UISplitViewControllerDelegate, UIPopoverControllerDelegate>
{
    UISplitViewController* _splitViewController;    //Shows list UITableView on the left, and details on the right
    UIToolbar* _toolbar;                            //Toolbar for the button that will show the popover, when in portrait orientation
    SEL _svcAction;                                 //The action from the toolbar
    id _svcTarget;                                  //The target object from the toolbar
    UIPopoverController* _popover;                  //The popover that might need to be dismissed
    BOOL _popoverShowing;                           //Whether the popover is currently showing or not
}

-(void) svcToolbarClicked: (id)sender;

我使用 _svcAction 和 _svcTarget 来解决 greenisus 的担忧,即他可能没有调用正确的函数。

下面是我的实现。为简洁起见,我省略了实例化 UISplitViewController 和子视图的代码。 显示所有显示/隐藏相关代码。

//the master view controller will be hidden so hook the popover
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc 
{   
    _popoverShowing = FALSE;
    if(_toolbar == nil) 
    {
        //set title of master button
        barButtonItem.title = @"Title goes here";

        //Impose my selector in between the SVController, and the SVController's default implementation
        _svcTarget = barButtonItem.target;
        _svcAction = barButtonItem.action;
        barButtonItem.target = self;
        barButtonItem.action = @selector(svcToolbarClicked:);

        //create a toolbar
        _toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 1024, 44)];
        [_toolbar setItems:[NSArray arrayWithObject:barButtonItem] animated:YES];
    }

    //add the toolbar to the details view (the second controller in the splitViewControllers array)
    UIViewController* temp = [_splitViewController.viewControllers objectAtIndex:1];
    [temp.view addSubview:_toolbar];
}

这是我的函数,它响应工具栏的点击。这可以处理用户点击并重新点击工具栏按钮的情况。

-(void) svcToolbarClicked: (id)sender
{
    if(_popoverShowing)
    {
        [_popover dismissPopoverAnimated:TRUE];
    }
    else 
    {
        //Perform the default SVController implementation
        [_svcTarget performSelector:_svcAction];
    }
    //Toggle the flag
    _popoverShowing = !_popoverShowing;
}

UISplitViewControllerDelegate 中的一些函数

//the master view (non-popover) will be shown again (meaning it is going to landscape orientation)
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)button 
{
    //remove the toolbar
    [_toolbar removeFromSuperview];
}

// the master view controller will be displayed in a popover (i.e. the button has been pressed, and the popover is about to be displayed.  
//Unfortunately triggers when the popover is ALREADY displayed.
- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController 
{   
    _popover = pc; //Grab the popover object  
    _popover.delegate = self;
}

上面的代码对于大多数情况来说已经足够了。但是,如果用户打开弹出框,然后通过单击屏幕上的其他位置将其关闭,则_popoverShowing布尔值将包含不正确的值,这将迫使用户点击工具栏按钮两次以重新打开弹出框。要解决此问题,请实现该UIPopoverControllerDelegate方法,如下面的代码片段。

//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    _popoverShowing = FALSE;
    _popover = nil;
}

这让我花了很长时间才弄清楚,深入研究文档和(我认为)StackOverflow 上的大多数 UISplitViewController 问题。我希望有人觉得它有用。如果是这样,我觊觎声望点。;-)

于 2010-04-17T16:13:04.067 回答
-1

伊丽莎白写道:

如果您点击弹出框之外的任何位置,您可以在不选择项目的情况下使弹出框消失,但如果用户再次点击该按钮,我也想让它消失。

首先,让我说,我要说的任何内容都不是针对个人的——不是那个意思。这一切都来自多年设计编程界面和研究 Apple 人机界面指南(以及拥有一位不断尝试教我正确做事方式的图形设计师)。它的意思是相反的观点,而不是咆哮。

您的建议对我来说是 UI 方面的问题,并且会在 Apple 审查应用程序时引起麻烦。您永远不应该让已知 UI 对象执行它无法正常执行的功能(例如:按钮从不显示然后释放视图/对象/窗口。切换执行此操作)。

例如,导航栏上的放大镜表示搜索(由 Apple 定义)。他们过去和将来都会继续拒绝使用它来缩放界面的应用程序。例如:Apple Rejects ConvertBotThe Odyssey: Trail of Tears(搜索页面)。拒绝中的语言总是相同的(粗体标出他们会为您引用的内容):

“……以非标准方式使用标准 iPhone/iPod 屏幕图像,可能导致用户混淆。更改标准 iPhone 图形、动作和图像的行为,或模拟这些图形、动作或图像的故障,违反了 iPhone 开发者计划协议,该协议要求应用程序遵守人机界面指南。”</p>

另外,如果你真的想要这个功能,问问自己:“为什么?”。如果是因为你自己喜欢它,那我真的会跳过它。大多数用户会对这种行为感到困惑,并且不会实际使用它,因为他们不知道这是一个可以使用的选项。Apple 在过去的 3 年中一直在培训 iPhoneOS 用户如何使用他们的操作系统和界面元素。作为程序员或设计师,您最不想做的事情就是花时间尝试培训用户如何使用您的应用程序。他们通常会从他们的设备中删除您的应用程序并转移到另一个类似的应用程序,而不是强迫自己学习的做事方式。

只是我的 $.02

于 2010-04-14T21:25:36.643 回答