展示并操作編輯菜單
編輯菜單是一個(gè)上下文菜單泌辫,它展示并提供了一些命令璃诀,這些命令能夠操作選中內(nèi)容香府,例如一個(gè)文本頁(yè)面中的文字或者圖片。編輯菜單是復(fù)制峰锁,剪切,粘貼操作的一個(gè)組成部分双戳。它默認(rèn)展示復(fù)制,剪切糜芳,粘貼飒货,選中以及全選的命令。然后峭竣,你可以添加一個(gè)自定義的條目到編輯菜單來(lái)對(duì)選中內(nèi)容進(jìn)行其他操作塘辅。
管理選中和編輯菜單
為了在一個(gè)頁(yè)面中復(fù)制或剪切一些東西,這些東西必須是被選中的皆撩】鄱眨可以是一串文本,一張圖片扛吞,一個(gè)URL呻惕,一個(gè)顏色,或者是其他種類的數(shù)據(jù)滥比,包括自定義對(duì)象亚脆。你必須自己管理頁(yè)面中選中的對(duì)象。如果用戶通過使用某種手勢(shì)選擇了頁(yè)面中的對(duì)象盲泛,你必須要處理這個(gè)事件濒持,記錄選中區(qū)域(取消選中之前已選中內(nèi)容),并在頁(yè)面上標(biāo)記出選中的內(nèi)容寺滚「逃可以允許用戶選中多個(gè)對(duì)象,執(zhí)行復(fù)制村视,剪切官套,粘貼操作,你必須自己實(shí)現(xiàn)這種多選行為。
注:對(duì)于處理觸摸事件虏杰,包括手勢(shì)的內(nèi)容讥蟆,查看Event Handling Guide for iOS
當(dāng)你的應(yīng)用識(shí)別出用戶已經(jīng)請(qǐng)求了編輯菜單——也就是產(chǎn)生了一次選中行為——你應(yīng)該完成以下幾步來(lái)展示菜單:
- 調(diào)用UIMenuController的sharedMenuController類方法獲取全局的實(shí)例。
- 計(jì)算選中區(qū)域的邊界纺阔,并將結(jié)果傳給setTargetRect:inView:方法瘸彤。編輯菜單將在這個(gè)區(qū)域的上面或者下面出現(xiàn)(取決于選中區(qū)域距離屏幕頂部及底部的距離)。
- 調(diào)用setMenuVisible:animated方法讓編輯菜單顯示出來(lái)笛钝。
下面代碼展示了你應(yīng)該如何在touchesEnded:withEvent:方法中展示編輯菜單质况,用以處理復(fù)制,剪切玻靡,粘貼操作结榄。(注意,示例代碼省略了處理選中的代碼囤捻。)代碼也展示了自定義頁(yè)面發(fā)送becameFirstResponder消息來(lái)確保成為接下來(lái)復(fù)制臼朗,剪切,粘貼操作的第一響應(yīng)者蝎土。
- (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];
}
}
菜單初始包括所有第一響應(yīng)者實(shí)現(xiàn)了UIResponderStandardEditActions方法的行為(copy: paste:等)视哑。在菜單出現(xiàn)之前,系統(tǒng)發(fā)送canPerformAction:withSender:消息到第一響應(yīng)者誊涯。在該方法的實(shí)現(xiàn)中挡毅,響應(yīng)者評(píng)估該命令(第一個(gè)參數(shù)selector中傳遞)是否適用于當(dāng)前場(chǎng)合。例如暴构,如果selector是paste:并且剪切板中沒有該頁(yè)面能夠處理的數(shù)據(jù)跪呈,響應(yīng)者應(yīng)當(dāng)返回NO,來(lái)取消粘貼命令的展示取逾。如果第一響應(yīng)者沒有實(shí)現(xiàn)canPerformAction:withSender:方法耗绿,或者沒有處理指定命令,消息將沿響應(yīng)鏈傳遞下去菌赖。
下面代碼展示了canPerform:withSender方法的實(shí)現(xiàn)缭乘,查找并匹配了cut:,copy:以及paste:方法×鹩茫基于當(dāng)前的選中文本以及剪切板內(nèi)容堕绩,會(huì)開啟或關(guān)閉復(fù)制,剪切邑时,粘貼等菜單命令奴紧。
- (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里調(diào)用了父類的實(shí)現(xiàn),父類就有機(jī)會(huì)處理子類選擇忽略的命令晶丘。
注意菜單命令在執(zhí)行后黍氮,可能會(huì)改變其他菜單命令唐含。例如,當(dāng)用戶執(zhí)行了全選操作沫浆,復(fù)制和剪切操作應(yīng)當(dāng)出現(xiàn)在菜單中捷枯。在這種情況下,響應(yīng)者可以在菜單始終可見的情況下通過調(diào)用menu controller的update方法更新菜單专执,這就導(dǎo)致了canPerformAcation:withSender:的調(diào)用淮捆。
添加自定義條目至編輯菜單
你可以添加自定義條目到編輯菜單。當(dāng)用戶點(diǎn)擊此項(xiàng)時(shí)本股,將發(fā)出一個(gè)命令攀痊,該命令將以特定應(yīng)用程序的方式影響當(dāng)前目標(biāo)。UIKit通過target-action機(jī)制完成該目的拄显。該條目的點(diǎn)擊導(dǎo)致了一個(gè)行為消息被發(fā)送到響應(yīng)鏈中第一個(gè)能處理該消息的對(duì)象苟径。下圖展現(xiàn)了一個(gè)自定義條目的例子
![](https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/Art/custom_menu_item_2x.png)
UIMenuItem的實(shí)例代表自定義條目。UIMenuItem對(duì)象有兩個(gè)屬性躬审,title和action selector棘街,都可以任意時(shí)刻修改。要實(shí)現(xiàn)一個(gè)自定義菜單條目承边,你必須初始化這個(gè)UIMenuItem實(shí)例的這些屬性蹬碧,將該實(shí)例添加到menu controller的自定義菜單條目數(shù)組中,并在合適的響應(yīng)者類中實(shí)現(xiàn)該命令的操作炒刁。
其他方面是各處通用的:使用UIMenuController的單例對(duì)象。在自定義或者重寫的頁(yè)面中誊稚,你設(shè)置了頁(yè)面為第一響應(yīng)者翔始,獲取menu controller單例,設(shè)置一個(gè)目標(biāo)rectangle里伯,通過調(diào)用setMenuVisible:animated:方法展示編輯菜單城瞎。下面代碼是一個(gè)添加自定義菜單項(xiàng)的簡(jiǎn)單例子。
- (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];
}