前言
今天有一個(gè)小需求,就是在UITextView里面長(zhǎng)按顯示菜單那里面去自定義菜單,不用系統(tǒng)默認(rèn)顯示的投储。本來(lái)一個(gè)很好實(shí)現(xiàn)的小功能衡招,網(wǎng)上一查有很多篱昔。但是我按照人家給的思路去做了之后發(fā)現(xiàn),新增的自定義菜單是有了始腾,但是系統(tǒng)的還是沒(méi)有去掉州刽。結(jié)果傻眼了。然后摸索了一陣子浪箭,突發(fā)奇想的就換了個(gè)思路搞好了∷胍危現(xiàn)在想一下,確實(shí)自己很二了奶栖。
正文
API分析
顯示菜單說(shuō)白了就是一個(gè)VC匹表,用于顯示咱們這種長(zhǎng)按特殊需求的小界面门坷。
進(jìn)入U(xiǎn)IMenuController的API你會(huì)發(fā)現(xiàn)這是一個(gè)單例類(lèi),至于怎么發(fā)現(xiàn)的袍镀,看下構(gòu)造方法就知道了:
+ (UIMenuController *)sharedMenuController;
就這么一個(gè)構(gòu)造方法拜鹤,而且你想一下,菜單顯示這個(gè)確實(shí)是單例實(shí)現(xiàn)的最佳范例呀流椒,不可能同時(shí)在一個(gè)Windows出現(xiàn)敏簿。
UIMenuController里面的內(nèi)容很少,基本都能看懂宣虾。不懂得百度一下也就知道惯裕,我也不多說(shuō)了。
UIMenuController只是一個(gè)外表顯示绣硝,一個(gè)VC構(gòu)建了一個(gè)空的界面蜻势,里面有什么就需要你自己去填充了,當(dāng)然不可能阿貓阿狗都能填充鹉胖,這時(shí)候就需要UIMenuItem了握玛。
UIMenuItem的API就只有一個(gè)方法
NS_CLASS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED @interface UIMenuItem : NSObject
- (instancetype)initWithTitle:(NSString *)title action:(SEL)action NS_DESIGNATED_INITIALIZER;
@property(nonatomic,copy) NSString *title;
@property(nonatomic) SEL action;
@end
熟悉不,和手勢(shì)的創(chuàng)建很像吧(本來(lái)想說(shuō)和UITabBarItem很像甫菠,但是仔細(xì)一想形式很像挠铲,作用很像,但是創(chuàng)建方法他們兩個(gè)有些不合適)寂诱。
這個(gè)方法就是給一個(gè)標(biāo)題一個(gè)事件拂苹,沒(méi)了√等鳎灰常簡(jiǎn)單有木有瓢棒。
第一次實(shí)踐進(jìn)行
然后我就按照我搜索的網(wǎng)上的各位人士給的方法去干:
- (void)viewDidLoad {
[super viewDidLoad];
//設(shè)置輸入視圖
self.textView = [[UITextView alloc]initWithFrame:CGRectMake(10, 20, CGRectGetWidth(self.view.frame) - 20, CGRectGetHeight(self.view.frame) - 40)];
self.textView.layer.borderWidth = 2;
self.textView.layer.borderColor = [UIColor redColor].CGColor;
self.textView.delegate = self;
[self.view addSubview:self.textView];
//設(shè)置菜單
UIMenuItem *menuItem = [[UIMenuItem alloc]initWithTitle:@"響應(yīng)菜單" action:@selector(selfMenu:)];
UIMenuController *menuController = [UIMenuController sharedMenuController];
[menuController setMenuItems:[NSArray arrayWithObject:menuItem]];
}
然后,使用一個(gè)UIResponder類(lèi)特意聲明去處理的一個(gè)方法丘喻,響應(yīng)者類(lèi)可以實(shí)現(xiàn)這個(gè)方法脯宿,以根據(jù)當(dāng)前的上下文顯示或移除編輯菜單上的命令。(摘抄過(guò)來(lái)的泉粉,我感覺(jué)說(shuō)的挺容易理解的)连霉。
//隱藏系統(tǒng)菜單的方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
//允許顯示
if (action == @selector(selfMenu:)) {
return YES;
}
//其他不允許顯示
return NO;
}
理論上,碼上這些搀继,應(yīng)該是可以隱藏系統(tǒng)的菜單顯示自定義的菜單了窘面,然后我去運(yùn)行:
這是怎么了?fuck the world叽躯。不是應(yīng)該是只顯示自定義的菜單了嗎财边,系統(tǒng)的不是應(yīng)該在UIResponder那個(gè)方法里面隱藏了嗎?剛開(kāi)始我有點(diǎn)懷疑我搜到的答案不對(duì)点骑,結(jié)果又搜了好幾個(gè)都是這樣酣难。然后自己鼓搗一會(huì)谍夭,結(jié)果還是好的,世界總是美好的憨募。
正確做法
繼承UITextView紧索,把實(shí)現(xiàn)自定義菜單代碼放在里面
#import "MyTextView.h"
@implementation MyTextView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
UIMenuItem *menuItem = [[UIMenuItem alloc]initWithTitle:@"響應(yīng)事件" action:@selector(selfMenu:)];
UIMenuController *menuController = [UIMenuController sharedMenuController];
[
menuController
setMenuItems:[NSArray arrayWithObject:menuItem]];
[menuController setMenuVisible:NO];
}
return self;
}
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(selfMenu:)) {
return YES;
}
return NO;
}
//自定義的事件
- (void)selfMenu:(id)sender{
}
@end
然后,使用自定義的UITextView
- (void)viewDidLoad {
[super viewDidLoad];
//設(shè)置輸入視圖
self.textView = [[MyTextView alloc]initWithFrame:CGRectMake(10, 20, CGRectGetWidth(self.view.frame) - 20, CGRectGetHeight(self.view.frame) - 40)];
self.textView.layer.borderWidth = 2;
self.textView.layer.borderColor = [UIColor redColor].CGColor;
self.textView.delegate = self;
[self.view addSubview:self.textView];
}
運(yùn)行:
正常運(yùn)行有木有菜谣,我感覺(jué)出問(wèn)題的原因應(yīng)該是和那個(gè)UIResponder的方法有問(wèn)題珠漂,因?yàn)槲以诮缑嫔线M(jìn)行的一切手勢(shì)事件他都會(huì)攔截的。所以直接在UITextView可能造成問(wèn)題尾膊,只是個(gè)人猜測(cè)媳危,大神知道了請(qǐng)告訴小弟呀。
結(jié)語(yǔ)
這也是一個(gè)小坑吧冈敛。估計(jì)會(huì)有人像我一樣遇到待笑,所以寫(xiě)在這,如果在遇到這個(gè)問(wèn)題的時(shí)候看到我這篇小文章抓谴,希望對(duì)你有幫助暮蹂。