问题
在我的iPad应用程序中,仅在按下并保持事件后才能将弹出窗口附加到按钮栏项目.但这似乎是撤消/重做的标准.其他应用程序如何做到这一点?
背景
我的UIKit(iPad)应用程序的工具栏中有一个撤消按钮(UIBarButtonSystemItemUndo).当我按下撤销按钮时,它会触发它的动作,即undo:,并且正确执行.
然而,在iPad上撤消/重做的"标准UE惯例"是按下撤销执行撤消,但按住按钮会显示一个弹出控制器,用户选择"撤消"或"重做"直到控制器被解除.
附加弹出控制器的常规方法是使用presentPopoverFromBarButtonItem:,我可以很容易地配置它.要仅在按住之后显示此内容,我们必须设置视图以响应"长按"手势事件,如此代码段中所示:
UILongPressGestureRecognizer *longPressOnUndoGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressOnUndoGesture:)]; //Broken because there is no customView in a UIBarButtonSystemItemUndo item [self.undoButtonItem.customView addGestureRecognizer:longPressOnUndoGesture]; [longPressOnUndoGesture release];
有了这个,在按下并保持视图后,方法handleLongPressOnUndoGesture:将被调用,在这个方法中,我将配置并显示undo/redo的popover.到现在为止还挺好.
这个问题是没有附加视图.self.undoButtonItem是一个UIButtonBarItem,而不是一个视图.
可能的解决方案
1)[理想] 将手势识别器附加到按钮栏项目.可以将手势识别器附加到视图,但UIButtonBarItem不是视图.它确实具有.customView的属性,但当buttonbaritem是标准系统类型时(在这种情况下它是),该属性为nil.
2)使用另一个视图.我可以使用UIToolbar,但这需要一些奇怪的命中测试,并且如果可能的话首先是一个全面的黑客攻击.我无法想到使用其他替代视图.
3)使用customView属性.像UIBarButtonSystemItemUndo这样的标准类型没有customView(它是nil).设置customView将删除它需要的标准内容.这将相当于重新实现UIBarButtonSystemItemUndo的所有外观和功能,如果可能的话.
题
如何将手势识别器附加到此"按钮"?更具体地说,如何在iPad应用程序中实现标准的按住 - 显示 - 重做 - 弹出窗口?
想法?非常感谢,特别是如果有人真的在他们的应用程序中工作(我在想你,omni)并想分享......
注意:这不再适用于iOS 11
尝试在工具栏的子视图列表中找到UIBarButtonItem的视图代替那个混乱,一旦将项添加到工具栏,您也可以尝试这样做:
[barButtonItem valueForKey:@"view"];
这使用键值编码框架来访问UIBarButtonItem的private _view变量,它保留了它创建的视图.
当然,我不知道Apple的私有API事件在哪里(这是用于访问公共类的私有变量的公共方法 - 不像访问私有框架来制作纯粹的Apple效果或任何东西),但是它确实有效,而且非常轻松.
这是一个老问题,但它仍然出现在谷歌搜索中,所有其他答案都过于复杂.
我有一个按钮栏,带有按钮栏项,按下时调用一个动作:forEvent:方法.
在该方法中,添加以下行:
bool longpress=NO; UITouch *touch=[[[event allTouches] allObjects] objectAtIndex:0]; if(touch.tapCount==0) longpress=YES;
如果是单击,则tapCount为1.如果是双击,则tapCount为2.如果是长按,则tapCount为零.
选项1确实是可能的.不幸的是,找到UIBarButtonItem创建的UIView是一件痛苦的事情.这是我发现它的方式:
[[[myToolbar subviews] objectAtIndex:[[myToolbar items] indexOfObject:myBarButton]] addGestureRecognizer:myGesture];
这比它应该更难,但这显然是为了阻止人们使用按钮的外观和感觉来愚弄.
请注意,固定/灵活空间不计为视图!
为了处理空间,你必须有一些方法来检测它们,遗憾的是SDK根本没有简单的方法来做到这一点.有解决方案,这里有一些:
1)在工具栏上从左到右将UIBarButtonItem的标记值设置为它的索引.这需要过多的手动工作才能使IMO保持同步.
2)将任何空格的启用属性设置为NO.然后使用此代码段为您设置标记值:
NSUInteger index = 0; for (UIBarButtonItem *anItem in [myToolbar items]) { if (anItem.enabled) { // For enabled items set a tag. anItem.tag = index; index ++; } } // Tag is now equal to subview index. [[[myToolbar subviews] objectAtIndex:myButton.tag] addGestureRecognizer:myGesture];
当然,如果您因某些其他原因禁用按钮,这可能存在陷阱.
3)手动编码工具栏并自己处理索引.由于您将自己构建UIBarButtonItem,因此您事先会知道它们在子视图中的索引.如有必要,您可以将此想法扩展到提前收集UIView以供以后使用.
您可以自己创建按钮,然后使用自定义视图添加按钮栏项,而不是在子视图中进行搜索.然后将GR连接到您的自定义按钮.
虽然这个问题已经超过一年了,但这仍然是一个非常烦人的问题.我已经向Apple提交了一份错误报告(rdar:// 9982911),我建议其他任何感觉相同的人都会复制它.