39 votes

Comment pouvez-vous ajouter un UIGestureRecognizer à un UIBarButtonItem comme dans le schéma d'annulation / redo commun UIPopoverController sur les applications iPad?

Problème

Dans mon iPad, je ne peux pas joindre une liste à un bouton de la barre d'élément seulement après la presse-et-organiser des événements. Mais ce qui semble être la norme pour annuler/refaire. Comment d'autres applications de ce faire?

Arrière-plan

J'ai un bouton annuler (UIBarButtonSystemItemUndo) dans la barre d'outils de mon UIKit (iPad) app. Lorsque j'appuie sur le bouton annuler, il déclenche un jeu d'action qui est annuler:, et qu'il s'exécute correctement.

Cependant, la "norme de l'UE de la convention" pour annuler/refaire sur iPad, c'est qu'en appuyant sur annuler exécute une opération d'annulation, mais en appuyant et en maintenant le bouton révèle une liste de contrôleur où l'utilisateur choisit "annuler" ou "refaire" jusqu'à ce que le contrôleur est rejeté.

La voie normale de joindre une liste contrôleur est avec presentPopoverFromBarButtonItem:, et je peux configurer ce assez facilement. Pour obtenir cette option pour afficher uniquement après avoir appuyé sur le bouton, nous avons la vue de répondre aux "appui long" événements de mouvement comme dans cet extrait:

UILongPressGestureRecognizer *longPressOnUndoGesture = [[UILongPressGestureRecognizer alloc] 
       initWithTarget:self 
               action:@selector(handleLongPressOnUndoGesture:)];
//Broken because there is no customView in a UIBarButtonSystemItemUndo item
[self.undoButtonItem.customView addGestureRecognizer:longPressOnUndoGesture];
[longPressOnUndoGesture release];

Avec cela, après une appuyez et maintenez sur le point de vue de la méthode handleLongPressOnUndoGesture: seront appelés, et que, dans cette méthode que j'ai de configurer et d'afficher la liste d'undo/redo. Pour l'instant, donc bon.

Le problème avec cela est qu'il n' est pas tenu à vous attacher. auto.undoButtonItem est un UIButtonBarItem, pas un point de vue.

Solutions possibles

1) [idéal] Joindre le geste de reconnaissance à la barre de boutons de l'élément. Il est possible de poser un geste de reconnaissance à vue, mais UIButtonBarItem n'est pas une vue. Il dispose d'une propriété pour .customView, mais que la propriété est nul lorsque le buttonbaritem est un système standard de type (dans ce cas c'est).

2) Utiliser un autre point de vue. Je pourrais utiliser le UIToolbar mais qui aurait besoin d'un peu bizarre hit-essais et d'être tout autour de hack, si possible en premier lieu. Il n'y a pas d'autre point de vue alternatif à l'utilisation que je peux penser.

3) Utiliser le customView de la propriété. Types Standard comme UIBarButtonSystemItemUndo ont pas customView (c'est nul). Réglage de la customView permet d'effacer le contenu standard dont il a besoin. Cela reviendrait à une re-mise en œuvre de toutes le look et la fonction de UIBarButtonSystemItemUndo, encore une fois si encore possible de le faire.

Question

Comment puis-je joindre un geste de reconnaissance pour ce "bouton"? Plus précisément, comment puis-je mettre en œuvre le standard appuyez sur et maintenez-pour-afficher-refaire-liste d'une application pour iPad?

Des idées? Merci beaucoup, surtout si quelqu'un a fait ce travail dans leur app (je pense à vous, omni) et veut partager...

25voto

Tustin2121 Points 1139

En lieu et place de ce désordre à essayer de trouver la UIBarButtonItem de la vue dans la barre d'outils de la sous-vue liste, vous pouvez également essayer cette solution, une fois que l'élément est ajouté à la barre d'outils:

[barButtonItem valueForKey:@"view"];

Cette fonction utilise la Valeur-Clé de Codage de cadre pour accéder à la UIBarButtonItem privé _view variable, où il maintient le point de vue qu'il a créé.

Certes, je ne sais pas où cela se situe au plan de Apple privée de l'API chose (ce qui est public de la méthode utilisée pour accéder à une variable privée d'une classe publique - et non comme un accès privé cadres pour faire de fantaisie Apple-seulement des effets ou quoi que ce soit), mais il fonctionne, et plutôt sans douleur.

13voto

utopian Points 21

C'est une vieille question, mais cela revient toujours dans les recherches sur Google, et toutes les autres réponses sont trop compliquées.

J'ai une barre de boutons, avec des éléments de barre de boutons, qui appelle une action: forEvent: méthode lorsque vous appuyez dessus.

Dans cette méthode, ajoutez ces lignes:

 bool longpress=NO;
UITouch *touch=[[[event allTouches] allObjects] objectAtIndex:0];
if(touch.tapCount==0) longpress=YES;
 

S'il s'agissait d'un simple toucher, tapCount en est un. Si vous appuyez deux fois, tapCount vaut deux. Si vous appuyez longuement, tapez sur Compteur = zéro.

9voto

v01d Points 1456

L'Option 1 est en effet possible. Malheureusement, c'est une chose douloureuse pour trouver le UIView que le UIBarButtonItem crée. Voici comment je l'ai trouvé:

[[[myToolbar subviews] objectAtIndex:[[myToolbar items] indexOfObject:myBarButton]] addGestureRecognizer:myGesture];

C'est plus difficile qu'elle devrait être, mais ce n'est clairement conçu pour empêcher les gens de faire les fous avec les boutons de regarder et de sentir.

Notez que Fixe/Flexible, les espaces ne sont pas comptés comme point de vue!

Afin de gérer des espaces, vous devez avoir un moyen de les détecter, et, malheureusement, le SDK n'a tout simplement pas de moyen facile de le faire. Il y a des solutions et voici quelques-uns d'entre eux:

1) Définir le UIBarButtonItem de l'étiquette de valeur de l'index de gauche à droite sur la barre d'outils. Cela nécessite trop de travail manuel pour conserver la synchronisation de l'OMI.

2) Définir les espaces activé propriété. Utilisez ensuite cet extrait de code pour définir les valeurs de la balise pour vous:

NSUInteger index = 0;
for (UIBarButtonItem *anItem in [myToolbar items]) {
    if (anItem.enabled) {
        // For enabled items set a tag.
        anItem.tag = index;
        index ++;
    }
}

// Tag is now equal to subview index.
[[[myToolbar subviews] objectAtIndex:myButton.tag] addGestureRecognizer:myGesture];

Bien sûr, cela a un écueil potentiel si vous désactivez un bouton pour une autre raison.

3) Manuellement le code de la barre d'outils et de gérer l'index de vous-même. Comme vous allez construire la UIBarButtonItem-même, de sorte que vous saurez à l'avance ce que l'indice qu'ils vont être dans les sous-vues. Vous pouvez étendre cette idée à la collecte de la UIView à l'avance pour une utilisation ultérieure, si nécessaire.

7voto

Ben Stiglitz Points 3054

Au lieu de chercher une sous-vue, vous pouvez créer le bouton vous-même et ajouter un élément de barre de boutons avec une vue personnalisée. Ensuite, vous connectez le GR à votre bouton personnalisé.

5voto

mc.schroeder Points 21

Bien que cette question date maintenant de plus d'un an, il s'agit toujours d'un problème assez ennuyant. J'ai soumis un rapport de bogue à Apple ( rdar: // 9982911 ) et je suggère à quiconque se sent le même de le dupliquer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X