2009-07-18 15 views
19

Sto cercando di ottenere i seguenti lavori di codice:Come far funzionare UIMenuController per una visualizzazione personalizzata?

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

L'istanza del menu è pronto, ma non mostra - la larghezza è sempre zero.

Oppure c'è qualche codice di esempio su questo argomento UIPasteboard/UIMenuController?

risposta

0

Non è necessario aggiungere UIMenuController* menu alla vista principale o secondaria, E.G. self.view? Penso che sia qualcosa come [self.view addSubView:menu.view]; O mi manca il punto della tua domanda. Si potrebbe anche voler impostare la cornice della vista del menu.

0

UIMenuController non ha una vista. Ho solo cercato qualche codice da iPhone Application Programming Guide: Event Handling di Apple:

Listing 3-4 Visualizzazione del menu di modifica

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

il commento ha il limite di caratteri - quindi inserisco il codice qui. –

+0

appena trovato una soluzione: Metti un UITextField invisibile nella vista e fallo diventare il primo risponditore. Quindi il menu copia-incolla verrà visualizzato correttamente. –

+0

Sto avendo lo stesso problema (la mia vista personalizzata è una sottoclasse di UITableViewCell, ma altrimenti è la stessa situazione). Un UITextField invisibile non mi sta aiutando. Il menu non viene ancora visualizzato e il menu Frame è ancora tutti zeri. Inoltre, la tastiera si apre ogni volta che faccio diventare UITextField un firstResponder. Puoi pubblicare qualche codice di esempio per il tuo lavoro? –

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

È necessario aggiungere più codice in canPerformAction: withSender: - dovrebbe controllare il cartoncino e lo stato di selezione. La Guida alla programmazione di applicazioni per iPhone di Apple fornisce diversi frammenti di codice.

7

Se si sta implementando una visualizzazione personalizzata e che vista si suppone sia il risponditore (al contrario di qualche altro punto di vista, come un UITextField), è necessario ignorare la funzione canBecomeFirstResponder nella vista e tornare SI:

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 

poi, quando si sta visualizzando il menu, si dovrebbe fare qualcosa di simile al seguente:

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

per visualizzare UIMenuController si deve aggiungere seguente

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

puoi dirmi come aggiungere l'opzione Avanti in questo ?? Lo sto cercando quindi aiutami in quello ..! – Vivek2012

2

Penso Cam è giusto, è necessario eseguire l'override sia canPerformAction e canBecomeFirstResponder

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

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 
48

non ero in grado di farlo funzionare anche quando ho letto tutte le vostre risposte. Sto presentando un codice pronto che funzionerà per tutti.

Diciamo che abbiamo una classe controller denominata Controller. Si può semplicemente incollare il seguente codice a questo controller di avere il menù lavorare sul suo punto di 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; 
} 

Ciò che deve essere fatto al fine per il menu di lavoro è che il firstResponder (nel nostro caso il nostro controller - vedi linea con [sé becomeFirstResponder]) deve essere in grado di diventare primo responder (Override metodo canBecomeFirstResponder attuazione causa predefinita restituisce NO) nonché - (BOOL) canPerformAction:(SEL)selector withSender:(id) sender che restituisce sI a qualsiasi azione che può essere eseguita da firstResponder

+5

Potrebbe essere necessario modificare tale asserzione per utilizzare canBecomeFirstResponder e inserire il resetFirstResponder all'esterno dell'asserzione;) – antsyawn

+0

Ciò funziona perfettamente. All'inizio ero un po 'preoccupato che [self becomeFirstResponder] avrebbe sollevato la tastiera, ma non è così. Grazie! –

+0

Nel metodo di copia, come posso ottenere il testo selezionato? per copiare su UIPasteboard –

6

Nel caso in cui qualcuno ha ancora problemi: il mio menu funzionava e un giorno smetteva di funzionare miracolosamente. Tutto il resto nella mia app funzionava ancora. Ora avevo rimosso il metodo [window makeKeyAndVisible] dal metodo application:didFinishLaunchingWithOptions: e mentre tutto il resto funzionava ancora, questo si rompe UIMenuController!

errore stupido da parte mia, difficile trovare il colpevole ...

+1

Grazie per questo. È venuto fuori che è successo a me, non sono sicuro di come sia stata rimossa la linea makeKeyAndVisible, ma senza di essa ho quasi distrutto il mio monitor e usato i suoi spigoli per impegnare Hari-Kari. –

+1

Grazie mille. Stavo presentando una lente di ingrandimento nella sua finestra, e avevo bisogno di fare di nuovo il tasto della finestra principale affinché UIMenuController funzionasse. – hatfinch

0

l'ho fatto nel modo seguente sotto. Basta chiamare il metodo che mostra il menu dopo un ritardo molto breve in init. Non volevo chiamarlo da View Controller e inoltre non ho trovato un evento che indica che la mia vista personalizzata è apparsa e sono pronto a mostrare il menu. Quindi in questo modo OK dal mio punto di vista. Il ritardo può essere inferiore, ma dipende da te.

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