TextKit框架详细解析 (十二) —— 文本编程指南之展示和管理编辑菜单(八)

版本记录

版本号 时间
V1.0 2018.09.01

前言

TextKit框架是对Core Text的封装,用简洁的调用方式实现了大部分Core Text的功能。 TextKit是一个偏上层的开发框架,在iOS7以上可用,使用它可以方便灵活处理复杂的文本布局,满足开发中对文本布局的各种复杂需求。TextKit实际上是基于CoreText的一个上层框架,其是面向对象的。接下来几篇我们就一起看一下这个框架。感兴趣的看下面几篇文章。
1. TextKit框架详细解析 (一) —— 基本概览和应用场景(一)
2. TextKit框架详细解析 (二) —— 基本概览和应用场景(二)
3. TextKit框架详细解析 (三) —— 一个简单布局示例(一)
4. TextKit框架详细解析 (四) —— 一个简单布局示例(二)
5. TextKit框架详细解析 (五) —— 文本编程指南之简介(一)
6. TextKit框架详细解析 (六) —— 文本编程指南之展示文本内容(二)
7. TextKit框架详细解析 (七) —— 文本编程指南之排版概念(三)
8. TextKit框架详细解析 (八) —— 文本编程指南之管理Text Fields and Text Views(四)
9. TextKit框架详细解析 (九) —— 文本编程指南之管理键盘(五)
10. TextKit框架详细解析 (十) —— 文本编程指南之复制、剪切和粘贴操作(六)
11. TextKit框架详细解析 (十一) —— 文本编程指南之输入数据的自定义视图(七)

Displaying and Managing the Edit Menu - 展示和管理编辑菜单

编辑菜单是一个上下文菜单,显示该菜单以提供可以对选择执行的命令,例如文本视图中的单词或图像。 编辑菜单是复制,剪切和粘贴操作的组成部分,它可以显示(可能)命令Copy, Cut, Paste, Select, and Select All。 但是,您可以将自定义菜单项添加到编辑菜单,以对选择执行其他类型的操作。


Managing the Selection and the Edit Menu - 管理选择和编辑菜单

要在视图中复制或剪切某些内容,或对其执行任何其他操作,必须选择“某些内容”。它可以是一系列文本,图像,URL,颜色或任何其他数据表示,包括自定义对象。您必须自己管理该视图中的对象选择。如果用户通过进行特定的触摸手势(例如,双击)选择视图中的对象,则必须处理该事件,在内部记录选择(并取消选择任何先前的选择),并且可能在视觉上指示新的选择。如果用户可以在视图中选择多个对象进行复制剪切粘贴操作,则必须实现该多选行为。

注意:Event Handling Guide for iOS中讨论了处理触摸事件的技术,包括手势识别器的使用。

当您的应用确定用户已请求编辑菜单(可能是进行选择的操作)时,您应完成以下步骤以显示菜单:

  • 1)调用UIMenuController的sharedMenuController类方法来获取全局菜单控制器实例。
  • 2)计算选择的边界,并使用生成的矩形调用setTargetRect:inView:方法。编辑菜单显示在此矩形的上方或下方,具体取决于选择与屏幕顶部或底部的距离。
  • 3)调用setMenuVisible:animated:方法(两个参数均为YES),以对选择上方或下方的编辑菜单的显示进行动画处理。

Listing 7-1说明了如何在touchesEnded:withEvent:方法的实现中显示编辑菜单,以处理复制,剪切和粘贴操作。 (请注意,该示例省略了处理选择的代码部分。)此代码段还显示自定义视图向自身发送一个becomeFirstResponder消息,以确保它是后续复制,剪切和粘贴操作的第一个响应者。

// Listing 7-1  Displaying the edit menu

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *theTouch = [touches anyObject];
 
    if ([theTouch tapCount] == 2  && [self becomeFirstResponder]) {
 
        // selection management code goes here...
 
        // bring up edit menu.
        UIMenuController *theMenu = [UIMenuController sharedMenuController];
        CGRect selectionRect = CGRectMake (currentSelection.x, currentSelection.y, SIDE, SIDE);
        [theMenu setTargetRect:selectionRect inView:self];
        [theMenu setMenuVisible:YES animated:YES];
 
    }
}

菜单最初包括第一响应者具有相应的UIResponderStandardEditActions方法实现的所有命令(copy:,paste:等等)。但是,在显示菜单之前,系统会向第一个响应者发送canPerformAction:withSender:消息,在许多情况下,该消息是自定义视图。在其实现此方法时,响应者评估命令(由第一个参数中的选择器指示)是否适用于当前上下文。例如,如果selector是paste:并且视图可以处理的类型的粘贴板中没有数据,则响应者应返回NO以禁止粘贴命令。如果第一个响应者没有实现canPerformAction:withSender:方法,或者没有处理给定的命令,则消息会在响应者链中向上传播。

Listing 7-2显示了canPerformAction:withSender:方法的实现,该方法查找与cut:,copy:paste:selectors匹配的消息;它根据当前选择上下文启用或禁用“复制”,“剪切”和“粘贴”菜单命令,对于粘贴,启用或禁用粘贴板的内容。

// Listing 7-2  Conditionally enabling menu commands

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    BOOL retValue = NO;
    ColorTile *theTile = [self colorTileForOrigin:currentSelection];
 
    if (action == @selector(paste:) )
        retValue = (theTile == nil) &&
             [[UIPasteboard generalPasteboard] containsPasteboardTypes:
             [NSArray arrayWithObject:ColorTileUTI]];
    else if ( action == @selector(cut:) || action == @selector(copy:) )
        retValue = (theTile != nil);
    else
        retValue = [super canPerformAction:action withSender:sender];
    return retValue;
}

请注意,此方法中的最后一个else子句调用超类实现,以便为任何超类提供处理子类选择忽略的命令的机会。

请注意,菜单命令在作用时可以更改其他菜单命令的上下文。 例如,如果用户选择视图中的所有对象,则复制和剪切命令应包含在菜单中。 在这种情况下,响应者可以在菜单仍然可见的情况下,在菜单控制器上调用update;这导致canPerformAction:withSender:在第一个响应者上重新调用。


Adding Custom Items to the Edit Menu - 将自定义项添加到编辑菜单

您可以将自定义项添加到编辑菜单。 当用户点击此项时,会发出一个命令,以特定于应用程序的方式影响当前目标。 UIKit框架通过target-action mechanism实现了这一点。 项目的点击导致将动作消息发送到响应者链中可以处理该消息的第一个对象。 图7-1显示了自定义菜单项的示例(“Change Color”)。

Figure 7-1 An edit menu with a custom menu item

UIMenuItem类的实例表示自定义菜单项。 UIMenuItem对象有两个属性,title and an action selector,您可以随时更改它们。 要实现自定义菜单项,必须使用这些属性初始化UIMenuItem实例,将实例添加到菜单控制器的自定义菜单项数组中,然后实现操作方法以在相应的响应程序子类中处理该命令。

实现自定义菜单项的其他方面对于使用单例UIMenuController对象的所有代码都是通用的。 在自定义或重写视图中,将视图设置为第一个响应者,获取共享菜单控制器,设置目标矩形,然后通过调用setMenuVisible:animated:显示编辑菜单。 Listing 7-3中的简单示例添加了一个自定义菜单项,用于在红色和黑色之间更改自定义视图的颜色。

// Listing 7-3  Implementing a Change Color menu item

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *theTouch = [touches anyObject];
    if ([theTouch tapCount] == 2) {
        [self becomeFirstResponder];
        UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Change Color" action:@selector(changeColor:)];
        UIMenuController *menuCont = [UIMenuController sharedMenuController];
        [menuCont setTargetRect:self.frame inView:self.superview];
        menuCont.arrowDirection = UIMenuControllerArrowLeft;
        menuCont.menuItems = [NSArray arrayWithObject:menuItem];
        [menuCont setMenuVisible:YES animated:YES];
    }
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {}
 
- (BOOL)canBecomeFirstResponder { return YES; }
 
- (void)changeColor:(id)sender {
    if ([self.viewColor isEqual:[UIColor blackColor]]) {
        self.viewColor = [UIColor redColor];
    } else {
        self.viewColor = [UIColor blackColor];
    }
    [self setNeedsDisplay];
}

注意:UIMenuController的arrowDirection属性(如Listing 7-3所示)允许您指定箭头附加到编辑菜单指向其目标矩形的方向。


Dismissing the Edit Menu - 移除编辑菜单

当您执行系统或自定义命令时,编辑菜单会自动隐藏。 您可以使用以下代码行保持菜单可见:

[UIMenuController sharedMenuController] .menuVisible = YES;

系统可以随时隐藏编辑菜单。 例如,当显示alert弹窗或用户点击屏幕的另一个区域时,它会隐藏菜单。 如果您的状态或显示取决于编辑菜单是否可见,您应该监听名为UIMenuControllerWillHideMenuNotification的通知并采取适当的操作。

后记

本篇主要讲述了展示和管理编辑菜单,感兴趣的给个赞或者关注~~~

你可能感兴趣的:(TextKit框架详细解析 (十二) —— 文本编程指南之展示和管理编辑菜单(八))