2009-10-07 7 views
3

J'ai un UIScrollView avec l'exigence que, lors d'un zoom, la contentSize.height doit rester la même. Un zoom de 200x100 devrait aboutir à un nouveau contentSize de 400x100 au lieu de 400x200, par exemple. J'aimerais faire mon propre dessin pendant que l'utilisateur effectue un zoom.zoom sur mesure pour mettre en œuvre un UIScrollView

Je ne pense pas que je peux utiliser le comportement de zooming normal de UIScrollView pour y parvenir, donc je suis en train de rouler mon propre. (Je pourrais juste le laisser faire son truc et ensuite redessiner mon contenu quand -scrollViewDidEndZooming: withView: atScale: est appelé, mais ce ne serait pas très joli).

Actuellement, je suis le sous-classement UIScrollView et essayer de faire mon propre lorsque deux doigts zooming sont à l'écran:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if ([touches count] != 2) { 
     [super touchesMoved:touches withEvent:event]; 
    } else { 
    // do my own stuff 
    } 
} 

Je pensais que par des raisons impérieuses touchesBegan: withEvent :, touchesMoved: withEvent :, touchesEnded: withEvent: et touchCancelled: withEvent: de cette façon devrait fonctionner, mais ce n'est pas le cas.

Une tentative ayant échoué était de placer une vue transparente sur le dessus du scrollview et envoyer des touches que je ne suis pas intéressé par la scrollview:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if ([touches count] != 2) { 
     [self.theScrollView touchesMoved:touches withEvent:event]; 
    } else { 
    // do my own stuff 
    } 
} 

Toute aide serait appréciée.

Merci, Thomas

Répondre

3

Vous ne serez probablement pas en mesure de maintenir des performances décentes pendant le zoom si vous essayez de redessiner votre contenu sur chaque image d'un événement de zooming. Je vous recommande de l'approche de laisser le zoom UIScrollView une version réduite de votre dessin ou arrière, puis redessiner le contenu d'être forte à la fin du zoom dans le -scrollViewDidEndZooming: withView: atScale: méthode déléguée. C'est ce que je fais dans ma demande, et cela finit par fonctionner très bien.

Il existe quelques astuces pour redimensionner votre vue de contenu correctement à la fin d'un zoom, que je décris dans this answer. Fondamentalement, vous devez intercepter le paramètre d'une transformation à votre vue de contenu afin que vous puissiez le définir à un facteur d'échelle de 1 lorsque vous redessinez votre contenu. Vous devrez également garder une trace de ce facteur d'échelle, car UIScrollView ne le fait pas, et utiliser ce facteur d'échelle pour ajuster la transformation que UIScrollView tente d'appliquer à votre vue de contenu avec les opérations de zoom suivantes.

Vous pourriez utiliser une modification de cette technique pour forcer un redessin de votre contenu pendant le zoom pincement, mais dans mes tests cela a fini par être beaucoup trop saccadé pour fournir une bonne expérience utilisateur.

+0

OK, merci, je vais essayer d'intercepter setTransform: et redessiner la vue à la fin du zoom pincement. Je pourrais essayer de redessiner complètement mon point de vue et voir à quoi ressemble la performance. Je ne serai pas capable de le faire aujourd'hui, mais je vous dirai comment je vais. –

+0

J'ai fait un test rapide, intercepté setTransform:, et essayé de redessiner mes vues de contenu à chaque fois. Vous avez raison, ce n'est pas une option sur l'appareil pour des raisons de performances. Je vais aller avec votre approche recommandée de laisser zoom UIScrollView, puis redessiné dans -scrollViewDidEndZooming: avecView: atScale :. Merci. –

0

Je ne sais pas ce que vous entendez par là:

Je pensais que par des raisons impérieuses touchesBegan: withEvent :, touchesMoved: withEvent :, touchesEnded: withEvent : et touchesCancelled: withEvent: de cette façon devrait fonctionner, mais il ne fonctionne pas.

Ne vous obtenez pas les événements? Vous devriez recevoir les événements, mais je pense qu'il y a une erreur de logique dans votre instruction if qui a peut-être empêché cela de fonctionner.

if ([touches count] != 2) 

Ceci est un problème, car la probabilité que les deux touches se produisent précisément en même temps est faible. Vous voudrez être capable de gérer lorsque les touches se produisent de manière indépendante, ainsi que lorsque l'utilisateur tient un doigt immobile, et déplace l'autre. Dans ces scénarios (qui sont communs), vous ne pouvez obtenir qu'une seule touche dans ce NSSet, même si l'autre est toujours valide.

La solution à la manipulation des touches est bien de se rappeler certaines choses au sujet qui touche sont venus et qui touche gauche. Rappelez-vous que l'adresse de l'UITouch ne change pas pendant la durée de vie du contact, vous pouvez donc comparer les adresses en toute sécurité pour vous assurer que vous avez toujours le même contact que précédemment et suivre son cycle de vie.

Si vous ne recevez pas les événements tactiles, alors c'est un problème tout à fait différent, vous devrez peut-être tourner mettre multiTouchEnabled:YES

+0

Je fondais sur ce chapitre en commençant iPhone 3 Programmation où les touches NSSet était utilisé pour accéder aux touches. Je n'étais pas au courant que ce NSSet pourrait ne pas contenir toutes les touches à chaque fois touchesMoved: withEvent: est appelé. –

+0

J'avais multiTouch activé sur, mais il me semble que UIScrollView fait quelque chose de fantaisie là-bas dans les coulisses. Serait-il possible qu'il ajoute une nouvelle vue sur lui-même pour gérer tous les événements tactiles une fois que l'utilisateur commence à défiler ou à zoomer? C'était mon idée, mais je n'ai pas vraiment passé beaucoup de temps à approfondir cette théorie. –

0

J'essaie de faire la même chose et je veux vraiment pouvoir redessiner pendant le zoom. Fixez-le à la fin dans scrollViewDidEndZooming: withView: atScale n'est pas vraiment assez bon.

La façon dont je le fais est de passer une vue factice dans viewForZoomingInScrollView: et lire la hauteur de cette vue fictive et définir le cadre sur la vue du contenu réel à ce que je veux. Parce que le cadre change, cela signifie que drawRect est appelé à chaque fois. Ça semble bien sur le simulateur, je dessine juste quelques lignes. Mais je ne possède pas de périphérique, donc je ne peux pas le tester correctement.

également dans le code que vous avez, vous avez touchesBegan: withEvent: mais vous transférez au super touchesMoved: withEvent: au lieu de touchesBegan: withEvent:

+0

J'ai essayé à chaque fois de redessiner ma vue de contenu, et même si cela fonctionne très bien dans le simulateur, ce n'est même pas acceptable à distance sur mon iPhone 3G. Avec les données que j'ai testées, je dessinais seulement 9 CGPaths. Mon UIScrollView est actuellement transparent, ce qui a probablement un impact sur les performances. Quoi qu'il en soit, vous devriez essayer de tester votre code sur un périphérique réel - je ne serais pas surpris si le redessin pendant le zoom sera trop lent dans votre cas aussi. –

Questions connexes