Pytanie Jak uzyskać działanie UIMenuController dla niestandardowego widoku?


Próbuję uzyskać następujący kod działa:

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

Instancja menu jest gotowa, ale nie jest wyświetlana - szerokość zawsze wynosi zero.

Czy jest jakiś przykładowy kod na ten temat UIPasteboard/UIMenuController temat?


19
2017-07-18 02:58


pochodzenie




Odpowiedzi:


Nie byłem w stanie sprawić, żeby działało, nawet gdy przeczytałem wszystkie twoje odpowiedzi. Prezentuję gotowy kod, który będzie działał dla wszystkich.

Powiedzmy, że mamy klasę kontrolera o nazwie Controller. Możesz po prostu wkleić poniższy kod do kontrolera, aby menu działało na jego widoku:


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

Co trzeba zrobić, aby menu działało, to firstResponder (w naszym przypadku nasz kontroler - patrz linia z [self becomeFirstResponder]) musi być w stanie zostać pierwszym responderem (metoda override canBecomeFirstResponder powoduje, że domyślna implementacja zwraca NO) tak jak - (BOOL) canPerformAction:(SEL)selector withSender:(id) sender która powinna zwracać TAK na dowolne działanie, które może być wykonane przez firstResponder


48
2017-10-06 13:01



Możesz chcieć zmienić to stwierdzenie, aby użyć canBecomeFirstResponder, i umieścić obiekt beFirstResponder poza dowodami assert;) - antsyawn
To działa idealnie. Początkowo obawiałem się, że [self isFirstResponder] podniesie klawiaturę, ale tak się nie stało. Dziękuję Ci! - R.S
W metodzie kopiowania, w jaki sposób mogę uzyskać wybrany tekst? skopiować do UIPasteboard - Khaled Annajar


Jeśli implementujesz niestandardowy widok i ten widok ma być odpowiedzią (w przeciwieństwie do innego widoku, takiego jak UITextField), musisz zastąpić funkcję canBecomeFirstResponder w widoku i wrócić TAK:

- (BOOL)canBecomeFirstResponder {
    return YES;
}

wtedy, gdy wyświetlasz menu, powinieneś zrobić coś takiego:

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

7
2017-09-02 03:37





Na wypadek, gdyby ktoś nadal miał problemy: moje menu działało i pewnego dnia przestało działać cudownie. Cała reszta w mojej aplikacji wciąż działała. Teraz usunąłem [window makeKeyAndVisible] metoda z application:didFinishLaunchingWithOptions: i wszystko inne nadal działa, to się psuje UIMenuController!

Głupi błąd po mojej stronie, trudno znaleźć winnego ...


6
2017-09-21 19:20



Dziękuję Ci za to. Okazuje się, że stało się to dla mnie, nie jestem pewien, jak usunięto linię makeKeyAndVisible, ale bez niej prawie zniszczyłem mój monitor i użyłem jego ostrych krawędzi, by zatwierdzić Hari-Kari. - Rob Booth
Dziękuję Ci bardzo. Prezentowałem lupkę we własnym oknie i musiałem ponownie ustawić klawisz okna głównego, aby UIMenuController działał. - hatfinch


aby wyświetlić UIMenuController należy dodać następujące

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

4
2018-01-11 13:02



czy możesz mi powiedzieć, jak dodać opcję Forward w tym? Szukam tego, pomóż mi w tym ..! - Vivek2012


Myślę, że Cam ma rację, trzeba zastąpić zarówno canPerformAction, jak i canBecomeFirstResponder

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

- (BOOL)canBecomeFirstResponder {
    return YES;
}

2
2017-09-02 08:10





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

Musisz dodać więcej kodu w canPerformAction: withSender: - powinien sprawdzić tabelę i twój stan selekcji. Podręcznik programowania aplikacji dla iPhone'a zawiera kilka fragmentów kodu.


1
2017-07-18 21:53





Nie musisz dodawać UIMenuController* menu do głównego lub podrzędnego, E.G. self.view? Myślę, że to coś w stylu [self.view addSubView:menu.view]; Czy też brakuje mi punktu twojego pytania. Możesz również ustawić ramkę widoku menu.


0
2017-07-18 05:30





UIMenuController nie ma widoku. Właśnie przeszukałem kod od Apple'a Podręcznik programowania aplikacji na iPhone'a: ​​Obsługa zdarzeń:

Listing 3-4 Wyświetlanie menu edycji

- (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
2017-07-18 07:17



komentarz ma ograniczenie znaków - więc umieszczam tutaj kod. - al_lea
Właśnie znalazłem obejście: Umieść niewidoczny UITextField w widoku i ustaw go jako pierwszy. Następnie menu kopiuj-wklej pojawi się poprawnie. - al_lea
Mam ten sam problem (mój niestandardowy widok jest podklasą UITableViewCell, ale poza tym jest to ta sama sytuacja). Niewidzialny UITextField mi nie pomaga. Menu nadal nie jest wyświetlane, a menuFrame nadal jest zerowe. Klawiatura pojawia się również za każdym razem, gdy UITextField jest pierwszym odpytywaniem. Czy możesz opublikować przykładowy kod do obejścia? - James Williams