web-dev-qa-db-ja.com

UIMenuControllerが表示されない

カスタム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];

エラーや例外はありませんが、メニューコントローラが表示されません。

63
indragie

次の3つのことを行う必要があります。

  1. ビューまたはビューコントローラーで -becomeFirstResponder を呼び出す必要があります。
  2. ビューまたはビューコントローラーは -canBecomeFirstResponder を実装する必要があります(YESを返します)。
  3. オプションで、ビューまたはビューコントローラーは、メニュー項目を個別に表示/非表示にする -canPerformAction:action withSender:sender を実装できます。
159
OZ Apps

答えは3つのことを述べていますが、うるさいために6つあります。

  1. メニューハンドラーはUIViewである必要があります。そうでない場合、-becomeFirstResponderは失敗します。
  2. メニューハンドラにはuserInteractionEnabled = YESが必要です
  3. メニューハンドラはビュー階層内にある必要があり、その-windowプロパティはinView:引数内のビューのウィンドウと同じである必要があります。
  4. -canBecomeFirstResponderを実装してYESを返す必要があります。
  5. [handler becomeFirstResponder]を呼び出す必要がありますbefore[menu setTargetRect:inView:]が呼び出されます。呼び出さないと、後者が失敗します。
  6. [menu setTargetRect:inView](少なくとも1回)と[menu setMenuVisible:animated:]を呼び出す必要があります。

具体的には、上記の1〜3の点で気が付きました。最初はUIResponderであるカスタムメニューハンドラクラスが必要でした。これにより、-becomeFirstResponderNOを返しました。次に、それはUIViewでしたが、失敗しました。次に、UIButtonがデフォルトでuserInteractionEnabled(ボタンの場合はYESNOの場合はUIViewsに設定されているため).

18
Kalle

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で言及されている手順に従います。

15
Snehal

以下は完全にコメントされた実際の例です...

サブクラスヘッダーファイルを表示

#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 にアクセスしてください

5
Durai Amuthan.H

IOS6で特に(そしてランダムに)誰かがこの問題を抱えている場合に備えて、デバイスで音声認識を有効にすることに関連する this SO を確認することをお勧めします(設定->一般->アクセシビリティ->選択の読み上げ:オン)。少数のユーザーがカスタムUIMenuItemsを表示できず、これが原因でした。

2
Matthew Leffler

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
    }
  }
}
1
profRic