2009-07-18 7 views
19

Je suis en train de faire le travail de code suivant:Comment faire pour que UIMenuController fonctionne pour une vue personnalisée?

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

L'instance de menu est prêt, mais il ne montre pas - la largeur est toujours égale à zéro.

Ou y a-t-il un exemple de code sur ce sujet UIPasteboard/UIMenuController?

Répondre

0

N'avez-vous pas besoin d'ajouter le UIMenuController* menu à la vue principale ou à la sous-vue, E.G. self.view? Je pense que c'est quelque chose comme [self.view addSubView:menu.view]; Ou est-ce que je manque le point de votre question. Vous pouvez également définir le cadre de la vue du menu.

0

UIMenuController n'a pas de vue. Je viens cherchai un code de iPhone Application Programming Guide: Event Handling de pomme:

de Listing 3-4 Affichage du menu d'édition

- (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]; 
    } 
} 
+0

le commentaire a la limite de caractères - donc je poste le code ici. –

+0

juste trouvé une solution de contournement: Mettez un UITextField invisible dans la vue et en faire le premier répondeur. Ensuite, le menu copier-coller apparaîtra correctement. –

+0

J'ai le même problème (ma vue personnalisée est une sous-classe de UITableViewCell, mais sinon c'est la même situation). Une invisible UITextField ne m'aide pas. Le menu n'est toujours pas affiché et le menuFrame est toujours à zéro. En outre, le clavier apparaît chaque fois que je fais un UITextField un premier répondeur. Pouvez-vous poster un exemple de code pour votre work-around? –

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; 
} 

Vous devez ajouter plus de code à canPerformAction: withSender: - il doit vérifier le carton et votre état de sélection. Le Guide de programmation d'applications iPhone d'Apple fournit plusieurs extraits de code.

7

Si vous implémentez une vue personnalisée et ce point de vue est censé être le répondeur (par opposition à un autre point de vue, comme un UITextField), vous devez remplacer la fonction canBecomeFirstResponder dans votre vue et revenir OUI:

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 

puis, lorsque vous affichez le menu, vous devez faire quelque chose comme ce qui suit:

- (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]; 
} 
4

pour afficher un UIMenuController doit ajouter suivante

- (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]; 
} 
+0

pouvez-vous me dire comment ajouter l'option avant dans ce ?? Je le cherche donc aide moi dans ça ..! – Vivek2012

2

Je pense que Cam est juste, doit passer outre à la fois canPerformAction et canBecomeFirstResponder

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

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 
48

Je n'ai pas pu le faire fonctionner même quand je lis toutes vos réponses. Je présente un code prêt qui fonctionnera pour tout le monde.

Disons que nous avons une classe de contrôleur appelée Controller. Vous pouvez simplement coller le code suivant à ce contrôleur pour avoir le menu de travail sur son point de vue:


- (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; 
} 

Ce qui doit être fait pour que le menu de travail est que le firstResponder (dans notre cas, notre contrôleur - voir la ligne avec [auto becomeFirstResponder]) doit être en mesure de devenir le premier répondeur (méthode remplacement canBecomeFirstResponder la cause implémentation par défaut retourne NO), ainsi que - (BOOL) canPerformAction:(SEL)selector withSender:(id) sender qui devrait revenir OUI à toute action qui peut être effectuée par firstResponder

+5

Vous pouvez changer cette assertion pour utiliser canBecomeFirstResponder, et mettre le getFirstResponder en dehors de l'assert;) – antsyawn

+0

Cela fonctionne parfaitement. J'étais un peu inquiet au début que [self becomeFirstResponder] amène le clavier, mais ce n'est pas le cas. Je vous remercie! –

+0

Dans la méthode de copie, comment puis-je obtenir le texte sélectionné? copier sur l'UIPasteboard –

6

Dans le cas où quelqu'un a encore Problèmes: Mon menu fonctionnait et un jour a cessé de fonctionner miraculeusement. Tout le reste dans mon application fonctionnait toujours. Maintenant, j'avais enlevé la méthode [window makeKeyAndVisible] de la méthode application:didFinishLaunchingWithOptions:, et alors que tout le reste fonctionnait encore, cela casse UIMenuController!

erreur stupide de mon côté, difficile de trouver le coupable ...

+1

Merci pour cela. Il s'avère que cela m'est arrivé, je ne sais pas comment la ligne makeKeyAndVisible a été retirée mais sans elle j'ai presque détruit mon moniteur et utilisé ses arêtes vives pour engager Hari-Kari. –

+1

Merci beaucoup. Je présentais une loupe dans sa propre fenêtre, et j'avais besoin de faire de nouveau la clé de la fenêtre principale pour que UIMenuController fonctionne. – hatfinch

0

Je l'ai fait de la façon suivante ci-dessous. Appelez simplement la méthode qui affiche le menu après un délai très court dans init. Je ne voulais pas l'appeler depuis View Controller et je n'ai pas trouvé d'événement indiquant que ma vue personnalisée est apparue et je suis prêt à afficher le menu. Donc, de cette façon OK de mon point de vue. Le retard peut être moindre, mais c'est à vous de décider.

@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; 
} 
Questions connexes