iphone cocoa-touch iphone-sdk-3.0 uimenucontroller

iphone - ¿Cómo hacer que UIMenuController funcione para una vista personalizada?



cocoa-touch iphone-sdk-3.0 (9)

¿No tiene que agregar el UIMenuController* menu a la subvista principal o la subvista, EG self.view ? Creo que es algo como [self.view addSubView:menu.view]; O me estoy perdiendo el punto de tu pregunta. También es posible que desee establecer el marco de la vista del menú.

Estoy tratando de obtener el siguiente código de trabajo:

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

La instancia del menú está lista pero no se muestra, el ancho siempre es cero.

¿O hay algún código de ejemplo en este tema de UIPasteboard/UIMenuController ?


Creo que Cam tiene razón, necesita reemplazar tanto canPerformAction como canBecomeFirstResponder

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


En caso de que alguien todavía tenga problemas: mi menú solía funcionar y algún día dejó de funcionar milagrosamente. Todo lo demás en mi aplicación todavía funcionaba. Ahora había eliminado el método [window makeKeyAndVisible] de la application:didFinishLaunchingWithOptions: method, y mientras todo lo demás seguía funcionando, ¡esto rompe UIMenuController !

Error estúpido de mi lado, difícil de encontrar el culpable ...


Lo hice de la siguiente manera a continuación. Simplemente llame al método que muestra el menú después de un breve retraso en init. No quise llamarlo desde View Controller y tampoco encontré un evento que indique que mi vista personalizada apareció y estoy listo para mostrar el menú. Así que de esta manera está bien desde mi perspectiva. El retraso puede ser menor, pero depende de usted.

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


No pude hacerlo funcionar incluso cuando leí todas sus respuestas. Estoy presentando un código listo que funcionará para todos.

Digamos que tenemos una clase de controlador llamada Controller. Simplemente puede pegar el siguiente código en este controlador para que el menú funcione en su vista:

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

Lo que se debe hacer para que el menú funcione es que el primerResponder (en nuestro caso, nuestro controlador - ver la línea con [self BecomeFirstResponder]) debe poder convertirse en el primer respondedor (método de anulación canBecomeFirstResponder porque la implementación predeterminada devuelve NO) también as - (BOOL) canPerformAction:(SEL)selector withSender:(id) sender que debe devolver SÍ a cualquier acción que pueda realizar firstResponder


Si está implementando una vista personalizada y se supone que esa vista es el respondedor (a diferencia de alguna otra vista, como un UITextField), debe anular la función canBecomeFirstResponder en su vista y devolver SÍ:

- (BOOL)canBecomeFirstResponder { return YES; }

luego, cuando está mostrando el menú, debe hacer algo como lo siguiente:

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


UIMenuController no tiene vistas. Acabo de buscar un código en la Guía de programación de aplicaciones para iPhone de Apple : Manejo de eventos :

Listado 3-4 Mostrando el menú de edición

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


para mostrar UIMenuController se debe agregar lo siguiente

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


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

Debe agregar más código en canPerformAction: withSender: - debe verificar el área de trabajo y el estado de selección. La Guía de programación de aplicaciones para iPhone de Apple proporciona varios fragmentos de código.