在UIWebView中自定义显示选中文字的编辑菜单项

来源:互联网 发布:淘宝插件哪个好用 编辑:程序博客网 时间:2024/06/05 22:47

在iOS系统中,所谓“编辑菜单(Editing Menu)”和“上下文菜单(Contextual Menu)”是有区别的,但在桌面操作系统中,我们常说的“右键菜单”就已经囊括了“编辑菜单”和“上下文菜单”。iOS将两者细分开来,大概是因为移动客户端显示屏大小限制,将所有菜单揉和在一起的话,必定导致超出显示范围,带来不好的操作体验。


Editing Menu



Contextual Menu

本文主要以UIWebView为例,以此作为文本载体讲解如何自定义显示自己所需的编辑菜单项,当然,你也可以换作UITextView或任何一种文本容器,思路都是一样的。

先来看看一些App对编辑菜单的实现效果吧。最好的实现当然还是苹果自家的应用,下图是iBooks的实现,无论是菜单的自定义项,还是菜单文字的国际化处理,都很完美。


iBooks' Editing Menu

与此相比,Amazon的Kindle应用功能稍显单一,但从自定义菜单的处理上来看,还不失大公司水准,除了没有兼顾到中文国际化语言,仍算是比较优秀的作品。也许会有人反驳说Kindle不兼容中文是因为在App Store中国区根本就无法下载此应用,但是不是要照顾一下生活在英语地区的不以英语为母语的那些人呢?Google在这一点上就做得很好,虽然中国区没有Google+这款应用,但只要将iPhone系统语言设置为中文,其菜单文本就会转换为相应语言,几乎所有iOS系统支持的语言,Google+都做了处理。产品做到这种程度,由不得你不佩服。


Kindle's Editing Menu


Google+ Editing Menu

然后来看一款名为Kobo的电子书应用,其亮点是社交化阅读和分享,但一些细节上的处理真的无法让人满意。当用户长按并选中某段文字时,会同时叠加出现系统内置和自定义显示的菜单项,这是怎样一种蛋疼的行为啊?更令人发指的是,它在中国区的评分居然达到四颗星,中国区用户是不是太好打发了?


Kobo's Editing Menu

好吧,既然国外大公司都这种水平,那就更没有理由对国内产品横加指责了。一向以优雅、完美著称的iWeekly居然也是如此,还是中英文混搭的哦:)


iWeekly's Editing Menu

可以进入正题了。首先要说明,如果没有特殊需求,只是想要显示选中文字的编辑菜单,那么触摸屏的长按事件(long press)不需要专门捕获处理。但是需要继承实现一个自定制的View类,视具体情况而定,本文继承实现一个UIWebView,并重写UIRespondercanPerformAction:withSender:方法。

欲控制内置菜单项的显示或隐藏,须先了解具体有哪些内置菜单项。iOS系统内置编辑菜单项包括copy, cut, paste等13种,它们对应的selector名称如下:

  • cut: 剪切选中文字到剪贴版。
  • copy: 拷贝/复制选中文字到剪贴版。
  • select: 当处于文本编辑模式时,选中光标当前位置的一个单词。
  • selectAll: 选中当前页所有文字。
  • paste: 粘贴剪贴版中的文本到当前光标位置。
  • delete: 处于文本编辑模式时,删除选中的文本。(since iOS 3.2)
  • _promptForReplace: 即为上面Google+图片中显示的“替换为...”菜单,点击之后会给出与当前选中单词相近的其他单词。
  • _showTextStyleOptions: 处于文本编辑模式时,用于编辑字体风格属性,如粗体/斜体等。
  • _define: 调用iOS系统内置的英语词典,解释选中的单词。如果内置词典中找不到所选单词,则该项不予显示。
  • _accessibilitySpeak: 朗读当前选中的文本。
  • _accessibilityPauseSpeak: 暂停朗读文本。
  • makeTextWritingDirectionRightToLeft: 调整选中文本的书写格式为从右至左。阿拉伯语会用到。(since iOS 5.0)
  • makeTextWritingDirectionLeftToRight: 调整选中文本的书写格式为从左至右。(since iOS 5.0)

以上带有下划线前缀的都属于iOS的私有API,开发者无法调用。剩余的这些公共selector都被定义在一个名为UIResponderStandardEditActions的informal protocol中,所谓informal protocol,就是在NSObject上定义一个category,详见苹果官方文档Objective-C基础部分的讲解。

UIResponderStandardEditActions定义在UIResponder接口中,每一个继承自UIResponder的具体类中都有各自不同的实现,比如UIWebView中就只实现了其中的copy:paste:,当然,还有一个私有的_define:。当你继承了一个UIWebView之后,就可以重写canPerformAction:withSender:这个消息,来控制是否显示某些系统内置菜单项。

// file: CustomWebView.h#import <Foundation/Foundation.h>@interface CustomWebView : UIWebView@end

// file: CustomWebView.m#import "CustomWebView.h"@implementation CustomWebView {}// 隐藏“定义”菜单项。- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {  if (action == @selector(_define:)) return NO;  return [super canPerformAction:action withSender:sender];}@end

你还可以显示一些UIWebView本身不支持的内置菜单,比如selectAll:,须注意,如果显示了父类中不支持的菜单,则必须在自定义的子类中实现该方法,否则,当用户点击菜单时,程序会不作任何响应,甚至崩溃。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {  if (action == @selector(selectAll:)) return YES;  return [super canPerformAction:action withSender:sender];}- (void)selectAll:(id)sender {  NSLog(@"selectAll: in custom web view.");}

接下来就可以讨论如何添加自定义的菜单项了,其实很简单,在CustomeWebView显示之前,向UIMenuController中添加一些自定义项即可,这是一个单例对象,一个应用中仅维护一个这样的实例。下面的代码向菜单列表中添加了一个名为Flag的项。

UIMenuItem *flag = [[UIMenuItem alloc] initWithTitle:@"Flag" action:@selector(flag:)];UIMenuController *menu = [UIMenuController sharedMenuController];[menu setMenuItems:[NSArray arrayWithObjects:flag, nil]];[flag release];

当然,记得对自定义菜单项的Title做国际化处理哦,这里就不赘述了。至于如何使系统内置的菜单项适应国际化语言,非常简单,只需在工程目录下添加对应语言代码的.lproj文件夹即可。如果你添加了一个zh.lproj的文件夹到工程目录下,并在该文件夹下新建一个名为InfoPlist.strings的空白文件,那么,当你的程序运行在系统语言被设定为中文的移动终端时,这些内置菜单项自然会显示为中文。下面是一个Demo的效果图。


Custom Editing Menu Demo

EOF


转摘自 http://braincoder.me/2012/01/custom-edit-menu-on-selection-in-uiwebview/

0 0
原创粉丝点击