我正在使用拆分视图模板来创建一个简单的拆分视图,当然在纵向模式下有一个弹出窗口。我正在使用模板生成的默认代码,添加/删除工具栏项并设置弹出控制器并将其删除。这两个方法是splitViewController:willShowViewController:...和splitViewController:willHideViewController:...
如果用户在显示弹出窗口时点击工具栏按钮,我试图找出如何使弹出窗口消失。如果你点击弹出窗口外的任何地方,你可以让弹出窗口消失而不选择项目,但如果用户再次点击按钮,我也想让它消失。
我被困住的地方是:似乎没有一种明显的,简单的方法来挂钩工具栏按钮的动作。我可以使用调试器告诉我在按钮上调用的操作是showMasterInPopover。我承认,我不熟悉以编程方式使用选择器。
我可以以某种方式编写动作并将其设置在工具栏上,而不会覆盖已存在的动作吗?例如添加一个调用现在那个的动作?或者我是否必须编写一个动作来显示/隐藏自己的弹出窗口(现在可能是由分割视图控制器在幕后进行的行为???)。
或者我错过了一种简单的方法来将此行为添加到此按钮而不更改为我设置的现有行为?
谢谢!
答案 0 :(得分:6)
所以事实证明,通过实现SplitViewController willPresentViewController方法点击barButtonItem可以使popover解除,如下所示:
- (void) splitViewController:(UISplitViewController *)svc
popoverController: (UIPopoverController *)pc
willPresentViewController: (UIViewController *)aViewController
{
if (pc != nil) {
[pc dismissPopoverAnimated:YES];
}
}
答案 1 :(得分:1)
因此,barButtonItem将UISplitViewController作为目标,并将showMasterInPopover:作为动作。我在文档中找不到它,所以我有点担心它不可以调用它,但我通过将目标更改为self(视图控制器)并将操作更改为自定义方法(如这样:
- (void)showMasterInPopover:(id)sender {
// ...insert custom stuff here...
[splitViewController showMasterInPopover:sender];
}
答案 2 :(得分:0)
没有代表做出真正的评论。 : - (
@Jann - 我很确定伊丽莎白想做的事情非常标准。例如,当您按下左上角的工具栏按钮时,预装在iPad上的Notes应用程序将关闭并打开弹出窗口。
答案 3 :(得分:0)
以下是我的解决方案。它通过挂钩UISplitViewController
的工具栏按钮事件处理程序,开始类似于greenisus的解决方案。我在控制器中使用一个标志来跟踪弹出窗口是否打开。最后,为了处理用户打开popover的情况,然后通过单击popover外部来关闭它,我实现了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问题。我希望有人觉得它很有用。如果是这样,我就贪图声望点。 ; - )
答案 4 :(得分:0)
也许你们只是把它复杂得太多,或者我读到了一些与你们想要做的完全不同的东西......但也许,这就是你们所有人都试图弄清楚的那样:
-(void)togglePopOverController {
if ([popOverController isPopoverVisible]) {
[popOverController dismissPopoverAnimated:YES];
} else {
[popOverController presentPopoverFromBarButtonItem:bbiOpenPopOver permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
答案 5 :(得分:-1)
如果您点击弹出窗口外的任何位置,您可以在不选择项目的情况下使弹出窗口消失,但如果用户再次点击该按钮,我还想让它消失。
首先,请允许我说,我要说的不是我个人所说的 - 这并不意味着这样。这一切都来自于多年设计编程接口和研究Apple人机界面指南(以及让图形设计师不断尝试教我正确的做事方式)。它是一种相反的观点,而不是一种咆哮。
对于我来说,你所建议的是一个问题用户界面问题,并且当Apple审核该应用时,这将是一个导致问题的问题。你永远不应该让一个已知的UI对象执行一个它不能正常执行的功能(例如:一个按钮从不显示然后发布一个视图/对象/ window。切换这样做)。
例如,导航栏上的放大镜表示搜索(由Apple定义)。他们过去和将来都会拒绝使用它来缩放界面的应用程序。例如:Apple Rejects ConvertBot或The Odyssey: Trail of Tears(在页面中搜索)。拒绝中的语言总是相同的(粗体标记他们会引用您的用法):
“...以非标准方式使用标准iPhone / iPod屏幕图像,可能导致用户混淆。更改标准iPhone图形,操作和图像的行为,或模拟这些图形,操作或图像的失败违反了iPhone开发人员计划协议,该协议要求应用程序遵守人机界面指南。”
另外,如果您真的想要这个功能,请问自己:“为什么?”。如果是因为你,你自己,喜欢它,那么我真的会跳过它。大多数用户会对此行为感到困惑,并且实际上不会使用它,因为他们不知道这是一个使用的选项。 Apple花了3年时间培训iPhoneOS用户如何使用他们的操作系统和界面元素。作为程序员或设计师,您最不想做的就是花时间尝试培训用户如何使用您的应用程序。他们通常会从您的设备中移除您的应用并转移到其他类似的应用,而不是强迫自己学习您的做事方式。
只是我的$ .02