在Keynote(以及其他应用程序)中,我注意到执行撤消/重做的“标准”界面是通过在工具栏上提供撤消按钮。
单击按钮(始终启用)取消最近的操作。 (如果没有最近的撤消操作,它将显示撤消/重做菜单。)
长按“撤消”按钮可打开“撤消/重做”菜单。
我搜索了实现此方法的方法,到目前为止我找到的最佳答案是following link。
我想知道是否有人知道更简单的方法?
谢谢!
答案 0 :(得分:4)
在审查了所有方法并与朋友讨论之后,下面是我使用的解决方案,对于UIBarButtonItem,它响应两个点击并长按(TapOrLongPressBarButtonItem)。
它基于以下原则:
...到目前为止 - 这种方法是在other SO thread - 我不喜欢这种方法,因为我找不到足够简单的方法使自定义视图看起来像iPad导航栏按钮...... Soooo ......
使用Water Lou的UIGlossyButton(感谢水!)。这个用法封装在子类中......
结果代码如下:
@protocol TapOrPressButtonDelegate;
@interface TapOrPressBarButtonItem : UIBarButtonItem {
UIGlossyButton* _tapOrPressButton;
__weak id<TapOrPressButtonDelegate> _delegate;
}
- (id)initWithTitle:(NSString*)title andDelegate:(id<TapOrPressButtonDelegate>)delegate;
@end
@protocol TapOrPressButtonDelegate<NSObject>
- (void)buttonTapped:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem;
- (void)buttonLongPressed:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem;
@end
@implementation TapOrPressBarButtonItem
- (void)buttonLongPressed:(UILongPressGestureRecognizer*)gesture {
if (gesture.state != UIGestureRecognizerStateBegan)
return;
if([_delegate respondsToSelector:@selector(buttonLongPressed:withBarButtonItem:)]) {
[_delegate buttonLongPressed:_tapOrPressButton withBarButtonItem:self];
}
}
- (void)buttonTapped:(id)sender {
if (sender != _tapOrPressButton) {
return;
}
if([_delegate respondsToSelector:@selector(buttonTapped:withBarButtonItem:)]) {
[_delegate buttonTapped:_tapOrPressButton withBarButtonItem:self];
}
}
- (id)initWithTitle:(NSString*)title andDelegate:(id<TapOrPressButtonDelegate>)delegate {
if (self = [super init]) {
// Store delegate reference
_delegate = delegate;
// Create the customm button that will have the iPad-nav-bar-default appearance
_tapOrPressButton = [UIGlossyButton buttonWithType:UIButtonTypeCustom];
[_tapOrPressButton setTitle:title forState:UIControlStateNormal];
[_tapOrPressButton setNavigationButtonWithColor:[UIColor colorWithRed:123.0/255 green:130.0/255 blue:139.0/255 alpha:1.0]];
// Calculate width...
CGSize labelSize = CGSizeMake(1000, 30);
labelSize = [title sizeWithFont:_tapOrPressButton.titleLabel.font constrainedToSize:labelSize lineBreakMode:UILineBreakModeMiddleTruncation];
_tapOrPressButton.frame = CGRectMake(0, 0, labelSize.width+20, 30);
// Add a handler for a tap
[_tapOrPressButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
// Add a handler for a long-press
UILongPressGestureRecognizer* buttonLongPress_ = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(buttonLongPressed:)];
[_tapOrPressButton addGestureRecognizer:buttonLongPress_];
// Set this button as the custom view of the bar item...
self.customView = _tapOrPressButton;
}
return self;
}
// Safe guards...
- (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
NSLog(@"%s not supported!", __FUNCTION__);
return nil;
}
- (id)initWithImage:(UIImage *)image landscapeImagePhone:(UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
NSLog(@"%s not supported!", __FUNCTION__);
return nil;
}
- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
NSLog(@"%s not supported!", __FUNCTION__);
return nil;
}
- (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action {
NSLog(@"%s not supported!", __FUNCTION__);
return nil;
}
- (id)initWithCustomView:(UIView *)customView {
NSLog(@"%s not supported!", __FUNCTION__);
return nil;
}
@end
您需要做的就是:
<强> 1。实例化如下:
TapOrPressBarButtonItem* undoMenuButton = [[TapOrPressBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Undo", @"Undo Menu Title") andDelegate:self];
<强> 2。将按钮连接到导航栏:
[self.navigationItem setLeftBarButtonItem:undoMenuButton animated:NO];
第3。实现TapOrPressButtonDelegate协议,你就完成了......
-(void)buttonTapped:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem {
[self menuItemUndo:barButtonItem];
}
-(void)buttonLongPressed:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem {
[self undoMenuClicked:barButtonItem];
}
希望这有助于其他任何人......
答案 1 :(得分:0)
如果您正在使用IB(或者在Xcode4中使用设计器......我猜它被称为),那么您可以选择&#34;撤消&#34;从第一个响应者并将该操作拖动到一个按钮。如果不能覆盖它,我可以给你更具体的说明。
这里看起来像
它在列的左下方&#34;已接收的操作&#34;在底部
答案 2 :(得分:0)
我相信密钥实际上是在UINavigationBar本身。与UIButton或其他普通触摸跟踪对象不同,我怀疑UIBarItems不会处理他们自己的触摸。它们不继承UIResponder或UIControl方法。但是UINavigationBar当然可以。我个人已经多次直接向UINavigationBar添加手势。
我建议您覆盖UINavigationBar子类中的触摸处理,并检查其子项的触摸。如果孩子是你的特殊撤销按钮,你可以相应地处理它。
答案 3 :(得分:0)
UIButton* undoButton = [UIButton buttonWithType:UIButtonTypeCustom];
[undoButton addTarget:self action:@selector(undoPressStart:) forControlEvents:UIControlEventTouchDown];
[undoButton addTarget:self action:@selector(undoPressFinish:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* navButton = [[[UIBarButtonItem alloc] initWithCustomView:undoButton] autorelease];
self.navigationItem.rightBarButtonItem = navButton;
您不一定要将UIBarButtonItem添加为rightBarButtonItem,这是向您展示如何使用自定义视图创建UIBarButtonItem的简单方法,该自定义视图是您要处理事件的UIButton。
您需要通过维护状态来实现undoPressStart:和undoPressFinish:我会说,在开始时,存储当前的NSDate或时间的一些细粒度表示。完成后,如果检查已经过的时间以及是否超过某个阈值,则显示菜单 - 否则(以及从未捕获开始日期)执行撤消。
作为改进,您可能还想观察UIControlEventTouchDragExit事件以取消长按。