カスタムUIMenuControllerを作成してビューに表示しようとしています。これが私のコードです:
UIMenuController *menuController = [UIMenuController sharedMenuController];
UIMenuItem *listMenuItem = [[UIMenuItem alloc] initWithTitle:@"List" action:@selector(addList:)];
[menuController setMenuItems:[NSArray arrayWithObject:listMenuItem]];
[menuController setTargetRect:CGRectMake(50.0, 50.0, 0, 0) inView:self.view];
[menuController setMenuVisible:YES animated:YES];
[listMenuItem release];
エラーや例外はありませんが、メニューコントローラが表示されません。
次の3つのことを行う必要があります。
-becomeFirstResponder
を呼び出す必要があります。-canBecomeFirstResponder
を実装する必要があります(YES
を返します)。-canPerformAction:action withSender:sender
を実装できます。答えは3つのことを述べていますが、うるさいために6つあります。
-becomeFirstResponder
は失敗します。userInteractionEnabled = YES
が必要です-window
プロパティはinView:
引数内のビューのウィンドウと同じである必要があります。-canBecomeFirstResponder
を実装してYES
を返す必要があります。[handler becomeFirstResponder]
を呼び出す必要がありますbefore[menu setTargetRect:inView:]
が呼び出されます。呼び出さないと、後者が失敗します。[menu setTargetRect:inView]
(少なくとも1回)と[menu setMenuVisible:animated:]
を呼び出す必要があります。具体的には、上記の1〜3の点で気が付きました。最初はUIResponder
であるカスタムメニューハンドラクラスが必要でした。これにより、-becomeFirstResponder
はNO
を返しました。次に、それはUIView
でしたが、失敗しました。次に、UIButton
がデフォルトでuserInteractionEnabled
(ボタンの場合はYES
、NO
の場合はUIView
sに設定されているため).
UIMenuController
は、ビューが最初のレスポンダーであり、かつ
- (BOOL)canPerformAction
メソッドはYES
を返します
したがって、メニューコントローラーがボタンクリックで表示される場合、ボタンアクションの最初の行は[self becomeFirstResponder]
。注:ここでのセルフは、メニューを表示するビューです。
メニューを長押しジェスチャーで表示する場合は、書き込む前にUIView
と長押しイベントにlongPressGestureを追加します
[menuController setTargetRect:CGRectMake(50.0, 50.0, 0, 0) inView:self.view];
[menuController setMenuVisible:YES animated:YES];
書く [self becomeFirstResponder];
次に、OZで言及されている手順に従います。
以下は完全にコメントされた実際の例です...
サブクラスヘッダーファイルを表示
#import <Foundation/Foundation.h>
@interface MenuControllerSupportingView : UIView
{
}
@end
サブクラスのソースファイルを表示
#import "MenuControllerSupportingView.h"
@implementation MenuControllerSupportingView
//It's mandatory and it has to return YES then only u can show menu items..
-(BOOL)canBecomeFirstResponder
{
return YES;
}
-(void)MenuItemAClicked
{
NSLog(@"Menu item A clicked");
}
-(void)MenuItemBClicked
{
NSLog(@"Menu item B clicked");
}
-(void)MenuItemCClicked
{
NSLog(@"Menu item C clicked");
}
//It's not mandatory for custom menu items
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if(action == @selector(MenuItemAClicked))
return YES;
else if(action == @selector(MenuItemBClicked))
return YES;
else if(action == @selector(MenuItemCClicked))
return YES;
else
return NO;
}
コントローラのヘッダーファイルを表示する
#import <UIKit/UIKit.h>
@interface ViewController1 : UIViewController
@end
コントローラのソースファイルを表示する
#import "ViewController1.h"
#import "MenuControllerSupportingView.h"
@interface ViewController1 ()
{
MenuControllerSupportingView *vu;
}
@end
@implementation ViewController1
- (void)viewDidLoad
{
[super viewDidLoad];
vu=[[SGGI_MenuControllerSupportingView alloc]initWithFrame:CGRectMake(0,0,768,1024)];
[self.view addSubview:vu];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(200,200,200,30)];
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn setTitle:@"Show" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(SHowMenu) forControlEvents:UIControlEventTouchUpInside];
[vu addSubview:btn];
}
-(void)SHowMenu
{
UIMenuController *menucontroller=[UIMenuController sharedMenuController];
UIMenuItem *MenuitemA=[[UIMenuItem alloc] initWithTitle:@"A" action:@selector(MenuItemAClicked)];
UIMenuItem *MenuitemB=[[UIMenuItem alloc] initWithTitle:@"B" action:@selector(MenuItemBClicked)];
UIMenuItem *MenuitemC=[[UIMenuItem alloc] initWithTitle:@"C" action:@selector(MenuItemCClicked)];
[menucontroller setMenuItems:[NSArray arrayWithObjects:MenuitemA,MenuitemB,MenuitemC,nil]];
//It's mandatory
[vu becomeFirstResponder];
//It's also mandatory ...remeber we've added a mehod on view class
if([vu canBecomeFirstResponder])
{
[menucontroller setTargetRect:CGRectMake(10,10, 0, 200) inView:vu];
[menucontroller setMenuVisible:YES animated:YES];
}
}
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Viewクラスでは、canPerformActionで単独でreturn YESを書き込むと、カメラシンボル、カット、コピーなどのすべてのデフォルトメニューアイテムが表示されます。
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return YES;
}
もしカメラだけのようなものを見せたいなら
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if(action==@selector(_insertImage:))
return YES;
else
return NO;
}
あなたがすべての行動について知りたいなら
link にアクセスしてください
IOS6で特に(そしてランダムに)誰かがこの問題を抱えている場合に備えて、デバイスで音声認識を有効にすることに関連する this SO を確認することをお勧めします(設定->一般->アクセシビリティ->選択の読み上げ:オン)。少数のユーザーがカスタムUIMenuItems
を表示できず、これが原因でした。
Swift 3.0-
私の場合、VC TextViewでテキストを事前に選択し、ユーザーがその選択に対してアクションを実行するためのカスタムメニューを表示するようにしました。Kalle、特にsetMenuVisible
を最後にすることは、順序が非常に重要です。
VCでは、viewDidLoad
:
menuCont = UIMenuController.shared
let menuItem1: UIMenuItem = UIMenuItem(title: "Text", action: #selector(rtfView.textItem(_:)))
let menuItems: NSArray = [menuItem1]
menuCont.menuItems = menuItems as? [UIMenuItem]
VCでは、ユーザーがボタンを押すと:
@IBAction func pressed(_ sender: Any) {
self.textView.selectedRange = NSMakeRange(rangeStart, rangeLength)
self.textView.becomeFirstResponder()
menuCont.setTargetRect(CGRect.zero, in: self.textView)
menuCont.setMenuVisible(true, animated: true)
}
最後に、TextViewのサブクラスで:
class rtfView: UITextView {
override var canBecomeFirstResponder: Bool {
return true
}
override func canPerformAction(_ action: Selector, withSender sender: Any!) -> Bool {
if (action == #selector(textItem(_:))) {
return true
} else {
return false
}
}
}