20

次のコードを機能させようとしています。

UIMenuController * menu = [UIMenuController sharedMenuController];
[menu setTargetRect: CGRectMake(100, 100, 100, 100) inView: self.view];
[menu setMenuVisible: YES animated: YES];

メニュー インスタンスの準備はできていますが、表示されません。幅は常にゼロです。

UIPasteboard/UIMenuControllerまたは、このトピックに関するサンプル コードはありますか?

4

9 に答える 9

51

皆さんの回答を全部読んでもうまくいきませんでした。誰にとっても機能する準備ができたコードを提示しています。

Controller という名前のコントローラー クラスがあるとします。次のコードをこのコントローラーに貼り付けるだけで、ビューでメニューを機能させることができます。


- (void)loadView {
    [super loadView];

    UILongPressGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    [self.view addGestureRecognizer:gr];    
}

- (void) longPress:(UILongPressGestureRecognizer *) gestureRecognizer {
    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
        CGPoint location = [gestureRecognizer locationInView:[gestureRecognizer view]];
        UIMenuController *menuController = [UIMenuController sharedMenuController];
        UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"Item" action:@selector(menuItemClicked:)];

        NSAssert([self becomeFirstResponder], @"Sorry, UIMenuController will not work with %@ since it cannot become first responder", self);
        [menuController setMenuItems:[NSArray arrayWithObject:resetMenuItem]];
        [menuController setTargetRect:CGRectMake(location.x, location.y, 0.0f, 0.0f) inView:[gestureRecognizer view]];
        [menuController setMenuVisible:YES animated:YES];
    }
}

- (void) copy:(id) sender {
    // called when copy clicked in menu
}

- (void) menuItemClicked:(id) sender {
    // called when Item clicked in menu
}

- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender {
    if (selector == @selector(menuItemClicked:) || selector == @selector(copy:)) {
        return YES;
    }
    return NO;
}

- (BOOL) canBecomeFirstResponder {
    return YES;
}

メニューが機能するために行う必要があるのは、firstResponder (この場合はコントローラー - [self becomeFirstResponder] の行を参照) がファーストレスポンダーになれる必要があることです (メソッド canBecomeFirstResponder をオーバーライドすると、デフォルトの実装は NO を返します)。によって- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender実行できるすべてのアクションに YES を返す必要があります。firstResponder

于 2010-10-06T13:01:37.337 に答える
7

誰かがまだ問題を抱えている場合:私のメニューは以前は機能していましたが、ある日、奇跡的に機能しなくなりました。私のアプリの他のすべてはまだ機能していました。今、私は[window makeKeyAndVisible]メソッドをメソッドから削除しましたapplication:didFinishLaunchingWithOptions:、そして他のすべてがまだ機能している間、これは壊れUIMenuControllerます!

私の側の愚かなエラー、犯人を見つけるのは難しい...

于 2011-09-21T19:20:55.903 に答える
7

カスタム ビューを実装していて、そのビューが (UITextField などの他のビューではなく) レスポンダーであると想定されている場合は、ビューで canBecomeFirstResponder 関数をオーバーライドして YES を返す必要があります。

- (BOOL)canBecomeFirstResponder {
    return YES;
}

次に、メニューを表示しているときに、次のようなことを行う必要があります。

- (void)myMenuFunc {
    if (![self becomeFirstResponder]) {
        NSLog(@"couldn't become first responder");
        return;
    }

    UIMenuController *theMenu = [UIMenuController sharedMenuController];
    CGRect selectionRect = CGRectMake(0, 0, 0, 0);
    [theMenu setTargetRect:selectionRect inView:self];
    [theMenu setMenuVisible:YES animated:YES];
}
于 2009-09-02T03:37:34.200 に答える
4

UIMenuController を表示するには、以下を追加する必要があります

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(cut:))
        return NO;
    else if (action == @selector(copy:))
        return YES;
    else if (action == @selector(paste:))
        return NO;
    else if (action == @selector(select:) || action == @selector(selectAll:))
        return NO;
    else
        return [super canPerformAction:action withSender:sender];
}
于 2010-01-11T13:02:36.413 に答える
3

Cam は正しいと思います。canPerformAction と canBecomeFirstResponder の両方をオーバーライドする必要があります

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(doSomething:)) {
        return YES;
    }
    return NO;
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}
于 2010-09-02T08:10:40.200 に答える
1
// MyView.h

@interface MyView : UIView {
    IBOutlet UITextField * textField_;
}

@end

// MyView.m

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"show menu");

    [textField_ becomeFirstResponder];
    // [self.window becomeFirstResponder];

    UIMenuController * menu = [UIMenuController sharedMenuController];
    [menu setTargetRect: CGRectMake(0, 0, 100, 10) inView: self];
    [menu setMenuVisible: YES animated: YES];

    NSLog(@"menu width %f, visible %d", menu.menuFrame.size.width, menu.menuVisible);
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    return YES;
}

canPerformAction:withSenderにコードを追加する必要があります:-ペーストボードと選択状態を確認する必要があります。AppleのiPhoneアプリケーションプログラミングガイドには、いくつかのコードスニペットが用意されています。

于 2009-07-18T21:53:53.723 に答える
0

以下の方法で行いました。初期化の非常に短い遅延の後に、メニューを表示するメソッドを呼び出すだけです。ビュー コントローラーから呼び出したくありませんでした。また、カスタム ビューが表示され、メニューを表示する準備ができていることを示すイベントも見つかりませんでした。このように、私の観点からはOKです。遅延は少なくなる可能性がありますが、それはあなた次第です。

@implementation DTSignatureImageView

- (id)initWithImage:(UIImage *)image
{
    self = [super initWithImage:image];
    if(self){
        self.contentMode = UIViewContentModeScaleAspectFit;
        self.frame = CGRectMake(0, 0, image.size.width / 2.5, image.size.height / 2.5);
        self.userInteractionEnabled = YES;

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(signatureDidPan:)];
        [self addGestureRecognizer:pan];

        [self becomeFirstResponder];

        [self performSelector:@selector(showMenu) withObject:nil afterDelay:0.5];
    }

    return self;
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (void)showMenu
{
    UIMenuController *menu = [UIMenuController sharedMenuController];
    menu.menuItems = @[
       [[UIMenuItem alloc] initWithTitle:@"Apply" action:@selector(applySignature)],
       [[UIMenuItem alloc] initWithTitle:@"Update" action:@selector(updateSignature)],
       [[UIMenuItem alloc] initWithTitle:@"Clear" action:@selector(delegateSignature)]];
    [menu setTargetRect:self.bounds inView:self];
    [menu setMenuVisible:YES animated:YES];
}

- (NSArray *)menuActions
{
    static NSArray *actions = nil;
    if (actions == nil){
        actions = @[
                    NSStringFromSelector(@selector(applySignature)),
                    NSStringFromSelector(@selector(updateSignature)),
                    NSStringFromSelector(@selector(delegateSignature))];
    }

    return actions;
}

- (void) signatureDidPan: (UIPanGestureRecognizer *)gesture
{
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan: {
            [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
            break;
        }

        case UIGestureRecognizerStateEnded: {
            [self becomeFirstResponder];
            [self showMenu];
        }

        default:
            break;
    }

    CGPoint point = [gesture locationInView:gesture.view.superview];
    gesture.view.center = point;
}
于 2014-06-03T13:50:16.853 に答える
0

UIMenuController にはビューがありません。Apple の iPhone Application Programming Guide : Event Handlingからいくつかのコードを検索しました。

リスト 3-4 編集メニューの表示

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *theTouch = [touches anyObject];

    if ([theTouch tapCount] == 2  && [self becomeFirstResponder]) {

        // selection management code goes here...

        // bring up editing menu.
        UIMenuController *theMenu = [UIMenuController sharedMenuController];
        CGRect selectionRect = CGRectMake(currentSelection.x, currentSelection.y, SIDE, SIDE);
        [theMenu setTargetRect:selectionRect inView:self];
        [theMenu setMenuVisible:YES animated:YES];
    }
}
于 2009-07-18T07:17:00.807 に答える
0

UIMenuController* menuEG をメインまたはサブビューに追加する必要はありませんself.viewか? それは次のようなものだと思います[self.view addSubView:menu.view];または、あなたの質問の要点がわかりません. メニューのビューのフレームを設定することもできます。

于 2009-07-18T05:30:32.457 に答える