如何在UIWebView中添加自定义的编辑菜单困扰了很久。没想到意外的简单!
现在很多的内容提供类应用中,长按内容页会选中按的单词并且显示一个编辑菜单。如图:
独乐乐不如众乐乐。一篇好文章是需要大家一起欣赏的。一篇八卦文也是需要大家一起八卦的。
TabBar的一个分享按钮毕竟没法把这篇文章的亮点附带上。所以让用户通过长按,然后可以选择需要
分享的内容。最后再在弹出的菜单中选择“分享”去分享给好友。这样用户可以把打动他,的一句话分享出去。
用户选择的这句话不一定是文章的什么重点啊,中心啊(额,想到小时候语文课上的总结文章中心思想什么的了)。
但是肯定是能引起用户或者用户的这个圈子注意的一句话。这个选择权一定要给用户。
如何实现呢?简单!上代码:
1. 继承UIWebView
1 @interface HBRWebView : UIWebView 2 3 4 @end
2. 在构造函数中添加自定义菜单项
1 - (id)initWithFrame:(CGRect)frame{ 2 self = [super initWithFrame:frame]; 3 if (self) { 4 UIMenuItem *flag = [[UIMenuItem alloc] initWithTitle:@"分享" action:@selector(flag:)]; 5 UIMenuController *menu = [UIMenuController sharedMenuController]; 6 [menu setMenuItems:[NSArray arrayWithObjects:flag, nil]]; 7 [flag release]; 8 } 9 return self; 10 }
看到UIMenuItem了吗,这个就是自定义菜单项。Title设定为“分享”显示出来后就是“分享”。呵呵,说了句废话。
当这个菜单项被点击时执行的方法为 - (void)flag:(id)sender.
3. 添加菜单事件
1 - (void)flag:(id)sender{ 2 [self copy:nil]; 3 UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; 4 if (pasteBoard.string != nil) { 5 // DLog(@"%@", pasteBoard.string); 6 } 7 }
当我们的自定义菜单项被点击的时候,这个方法就会被执行。
在代码中的这句:
[self copy:nil];
把用户选定的文本内容拷贝到了剪切板中。下一句:
1 UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; 2 if (pasteBoard.string != nil) { 3 // DLog(@"%@", pasteBoard.string); 4 }
访问剪切板中复制的内容。这时你就可以把用户选定的内容拿到手里了。
到这里,我们需要实现的功能其实已经可以实现了。但是美中不足的是,如果系统自带的菜单不是你想要的呢?
所以还要看这里:
1 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 2 if (action == @selector(_define:)) { 3 return NO; 4 } 5 if (action == @selector(selectAll:)) { 6 return YES; 7 } 8 if (action == @selector(flag:)) { 9 return YES; 10 } 11 12 return [super canPerformAction:action withSender:sender]; 13 }
这个方法是重写了基类UIWebView中的实现。
1 if (action == @selector(_define:)) { 2 return NO; 3 }
直接屏蔽掉了系统自带的定义菜单项。在上面的上面的代码中selectAll:对应的返回了YES,如果返回NO,则全选这一项也不再显示。
知其然,也要知其所以然。对于自定义编辑菜单来说,UIWebView实现了UIResponder的canPerformAction:(SEL)action withSender:(id)sender
方法,默认的提供如下的菜单项对应的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
加下划线的就是所谓的私有方法了。开发者无权访问。所以前面去掉定义菜单项可能会有问题。写此文的时候我的应用还没发布,所以各位慎重权衡。
因为是在原型开发阶段,菜单项的国际化什么的各位自己把握。
下面是全部代码:
header
1 @interface MyWebView : UIWebView 2 3 4 @end
source
// // MyWebView.m // Created by Bruce on 13-8-5. // #import "MyWebView.h" @implementation MyWebView - (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { UIMenuItem *flag = [[UIMenuItem alloc] initWithTitle:@"定义" action:@selector(flag:)]; UIMenuController *menu = [UIMenuController sharedMenuController]; [menu setMenuItems:[NSArray arrayWithObjects:flag, nil]]; [flag release]; } return self; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(_define:)) { return NO; } if (action == @selector(selectAll:)) { return YES; } if (action == @selector(flag:)) { return YES; } return [super canPerformAction:action withSender:sender]; } - (void)flag:(id)sender{ [self copy:nil]; UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; if (pasteBoard.string != nil) { // DLog(@"%@", pasteBoard.string); } } @end
全文完。谢谢各位!