首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》13.4 UIMenuController

关灯直达底部

下面要为TouchTracker增加另一项功能:当用户选中某根线条时,TouchTracker要在用户手指按下的位置显示一个菜单。这个菜单要为用户提供一个删除选项。iOS SDK提供了一个名为UIMenuController的类,可以用来显示这类菜单。UIMenuController对象可以包含一组UIMenuItem对象(菜单项),并能在现有的视图上显示这些UIMenuItem对象。每个UIMenuItem对象都有自己的标题(会在菜单中显示)和动作方法(UIMenuItem对象会向第一响应对象发送动作消息)(见图13-3)。

图13-3 UIMenuController对象示例

每个iOS应用只有一个UIMenuController对象。当应用要显示该对象时,要先为它设置一组UIMenuItem对象,然后设置显示位置(矩形区域),最后将其设置为可见。在BNRDrawView.m的tap:中完成上述过程,使TouchTracker能够在用户按下线条时,在按下的位置显示菜单。此外,还要在tap:中实现隐藏菜单的功能:当手指按下的位置附近没有线条时,TouchTracker要取消当前选中的线条并隐藏UIMenuController对象,代码如下:

- (void)tap:(UIGestureRecognizer *)gr

{

NSLog(@“Recognized tap”);

CGPoint point = [gr locationInView:self];

self.selectedLine = [self lineAtPoint:point];

if (self.selectedLine) {

// 使视图成为UIMenuItem动作消息的目标

[self becomeFirstResponder];

// 获取UIMenuController对象

UIMenuController *menu = [UIMenuController sharedMenuController];

// 创建一个新的标题为“Delete”的UIMenuItem对象

UIMenuItem *deleteItem = [[UIMenuItem alloc]

initWithTitle:@“Delete” action:@selector(deleteLine:)];

menu.menuItems = @[deleteItem];

// 先为UIMenuController对象设置显示区域,然后将其设置为可见

[menu setTargetRect:CGRectMake(point.x, point.y, 2, 2) inView:self];

[menu setMenuVisible:YES animated:YES];

} else {

// 如果没有选中的线条,就隐藏UIMenuController对象

[[UIMenuController sharedMenuController] setMenuVisible:NO

animated:YES];

}

[self setNeedsDisplay];

}

要显示UIMenuController对象,还要满足一个条件:显示UIMenuController对象的UIView对象必须是当前UIWindow对象的第一响应对象。这也是为什么在tap:的起始部分会向BNRDrawView对象发送becomeFirstResponder消息。如果要将某个自定义的UIView子类对象设置为第一响应对象,就必须覆盖该对象的canBecomeFirstResponder方法。

在BNRDrawView.m中覆盖canBecomeFirstResponder方法并返回YES,代码如下:

- (BOOL)canBecomeFirstResponder

{

return YES;

}

构建并运行应用,选中某根线条,但是TouchTracker并不会按预期显示UIMenuController对象。这是因为该对象在显示前会枚举所有的UIMenuItem对象,检查第一响应对象是否实现了指定的动作方法。如果没有实现该方法,UIMenuController对象就不会显示相应的UIMenuItem对象;如果所有UIMenuItem对象的动作方法都没有实现,应用就不会显示UIMenuController对象。

在BNRDrawView.m中实现deleteLine:,显示UIMenuController对象和Delete菜单项,代码如下:

- (void)deleteLine:(id)sender

{

// 从已经完成的线条中删除选中的线条

[self.finishedLines removeObject:self.selectedLine];

// 重画整个视图

[self setNeedsDisplay];

}

构建并运行应用。画一根线条,按下并选中该线条,选择菜单中的Delete菜单项,TouchTracker应该会删除这根线条。