Glisser/déplacer une UIImageView

bnkbnk Membre
avril 2009 modifié dans API UIKit #1
Bonjour,

Je sais faire un glisser/déplacer d'une UIImageView dans une UIView classique.

Mais je n'arrive pas à  bouger une UIImageView dans un UIViewController ( c'est pourquoi vous pouvez lire self.view) à  travers une tabBar.
J'ai coché "user interaction enable" sur mon UIImageView.

Voici mes déclarations:
@interface MonQuizzViewController : UIViewController {<br />IBOutlet UIImageView *R1_btn2;<br />}<br />- (void)animationDeposer;<br />- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;<br />- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;<br />@end

Et le code:
/////////////////////////////////////////<br />// GESTION GLISSER/DEPLACER    //<br />/////////////////////////////////////////<br /><br />- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{<br />	<br />	UITouch *touch = [[event allTouches] anyObject];<br />	<br />	if ([touch view] == R1_btn2){<br />		R1_btn2.center = [touch locationInView:self.view];<br />	}<br /> }<br /><br />- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{<br /><br />	if(CGRectContainsRect([zoneSensible frame], [R1_btn2 frame])){<br />		[self animationDeposer];<br />	}<br />}<br /><br />- (void)animationDeposer {<br />	animationDeposer = YES;<br />	[UIView beginAnimations:nil context:NULL];<br />	[UIView setAnimationDuration:0.5];<br />	R1_btn2.transform = CGAffineTransformMakeScale(.001, .001);<br />	[UIView commitAnimations];<br />}


Voici une capture d'écran du programme:

c3a75eaacff66bd798a3b8fbc1614.png

Je souhaite donc glisser mes UIImageView 1 2 3 4 5 dans mon UIImageView "Toucher / Déposer".
Mon code est bon je pense c'est juste que ça ne détecte pas quand je touche l'UIImageView R1_btn2 qui correspond à  l'image du 1 rouge.

Le problème doit donc venir de mon if ici:
    if ([touch view] == R1_btn2){<br />        R1_btn2.center = [touch locationInView:self.view];<br />    }

En ajoutant des NSLog je vois que ([touch view] == R1_btn2) ne fonctionne pas.
Merci

Réponses

  • Philippe49Philippe49 Membre
    23:19 modifié #2
    et avec if( CGRectContainsPoint(R1_btn2.frame,[touch locationInView:self.view]) ) ?

    Redéfinitions inutiles dans  MonQuizzViewController
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
  • bnkbnk Membre
    23:19 modifié #3
    Merci pour ta réponse!

    J'ai donc retiré les définitions inutiles.
    if( CGRectContainsPoint(R1_btn2.frame,[touch locationInView:self.view])) ne fonctionne pas non plus.

    Info supplémentaire: UIImageView sont bien en premier plan.
  • Philippe49Philippe49 Membre
    avril 2009 modifié #4
    Personnellement, je séparerais :

    dans touchesBegan, détecter si on touche à  l'image, et lever un drapeau "dragging"
    dans touchesMoved, bouger l'image.
    dans touchesEnded, abaisser le drapeau.
  • Philippe49Philippe49 Membre
    23:19 modifié #5
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    if ([touch view] == imageView) dragging=YES;
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    if(!dragging) return;
    UITouch *touch = [[event allTouches] anyObject];
    imageView.center = [touch locationInView:self.view];
    }
    et dragging=NO dans touchesEnded ...
  • bnkbnk Membre
    23:19 modifié #6
    Merci je vais essayer ton code.

    J'avais fait ceci pour tester mais mon image ne bouge pas du tout, il y a donc un problème de détection mais à  quel niveau (Interface Builder, mon contrôlleur, ma view..) je ne sais pas.

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{<br />	UITouch *touch = [[event allTouches] anyObject];<br />	CGPoint location = [touch locationInView:touch.view];<br />	R1_btn.center = location;<br />}
    
  • bnkbnk Membre
    avril 2009 modifié #7
    ça ne fonctionne pas. :(
    Aurais tu un peu de temps pour regarder directement ce qui cloche dans mon code?
    Si tu as le temps, je t'enverrai le projet en MP.
    Une aide serait la bienvenue car je vais devoir utiliser beaucoup de les glisser/déplacer par la suite.
    merci
  • Philippe49Philippe49 Membre
    23:19 modifié #8
    dans 1238751232:

    ça ne fonctionne pas. :(
    Aurais tu un peu de temps pour regarder directement ce qui cloche dans mon code?
    Si tu as le temps, je t'enverrai le projet en MP.
    Une aide serait la bienvenue car je vais devoir utiliser beaucoup de les glisser/déplacer par la suite.
    merci

    Ok mais je n'ai pas de temps avant 17h ...
    - Essaie le code que je t'ai indiqué sur une mini-application (une UIImageView dans la vue principale) c'est une bonne méthode pour faire le point.
    - Mets des log complémentaires
  • bnkbnk Membre
    avril 2009 modifié #9
    Je viens donc de créer un nouveau projet sur une UIView classique.
    Tout fonctionne, mais je n'arrive toujours pas à  faire la même chose quand je l'intègre à  mon appli.
    <br />#import &quot;maVueController.h&quot;<br /><br />@implementation maVueController<br />- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />	NSLog(@&quot;touchesBegan&quot;);<br />	UITouch *touch = [[event allTouches] anyObject];<br />	if ([touch view] == monImage) dragging=YES;<br />}<br />- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{<br />	NSLog(@&quot;touchesMoved&quot;);<br />	if(!dragging) return;<br />	NSLog(@&quot;dragging&quot;);<br />	UITouch *touch = [[event allTouches] anyObject];<br />	monImage.center = [touch locationInView:self];<br />}<br />- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{<br />	NSLog(@&quot;touchesEnded&quot;);<br />	dragging=NO;<br />}<br />@end<br />
    

  • bnkbnk Membre
    avril 2009 modifié #10
    Problème réglé en créant une interface UIView à  la place d'une UIViewController.
    C'était donc le "self.view" qui passait pas.. :s

    Comment contourner le problème?
    Quel est la différence?

    Deux options:
    1) L'utilisation de mon contrôleur n'est peut être pas justifié puisque j'ai qu'une seule vue je change les setHidden en fonction de ce que j'ai besoin d'afficher. Il suffirait de créer une méthode initialisation à  la place du viewDidLoad et je passe mon UIViewControlleur en UIView.

    2) Je garde les deux.
  • Philippe49Philippe49 Membre
    23:19 modifié #11
    dans 1238762082:

    Problème réglé en créant une interface UIView à  la place d'une UIViewController.

    ce n'est surement pas la raison directe.

    dans 1238762082:

    C'était donc le "self.view" qui passait pas.. :s

    Peut-être si l'outliet view de ton contrôleur est mal réglé.

    Une erreur classique est de mal gérer le xib.
    Le controller de la vue doit être soit défini en outlet dans le xib principal, soit défini dans le code.
    Le File's Owner du xib piloté par ce controller doit être de la classe de ce controller, sans qu'un autre controller n'apparaisse dans ce second xib

  • bnkbnk Membre
    23:19 modifié #12
    En effet je ne comprend pas comment il faut gérer ces xib.

    Je t'invite à  regarder le projet que je t'ai joint en MP, tu pourras voir que j'ai fait un peu nimporte quoi (faute de compétences  :)beta:) en chargeant mes vues avec "Loaded from ..." et en utilisant "connected to" pour me connecter à  cette vue (quizz).

    Je vais essayer de mettre cette vue dans un xib, la charger comme les autre avec loaded from et de connecter le tout proprement..
  • bnkbnk Membre
    23:19 modifié #13
    J'ai fait les modifs, mais ça plante quand je souhaite afficher la page, il me sort des erreurs de ce type:

    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x10267b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key R3_btn.'


    Pourtant tout est bien relié dans ma nouvelle "window" ca doit venir d'ici:

    dans 1238765346:

    Une erreur classique est de mal gérer le xib.
    Le controller de la vue doit être soit défini en outlet dans le xib principal, soit défini dans le code.


    A quoi doit-on relier le contrôleur de la vue une fois qu'il est définit en outlet dans le xib principal?
    ps: si tu veux jetter un oeil, j'ai upload le projet modifié, il suffit donc d'aller à  la meme url en mettant "bnk2.zip" à  la place de "bnk.zip".
  • Philippe49Philippe49 Membre
    avril 2009 modifié #14
    J'ai entraperçu ton projet, mais cela me demanderait trop de temps de démasquer l'architecture.

    On a toujours intérêt à  gérer les vues principales en utilisant des xib séparés, ne serait-ce que pour laisser la possibilité à  l'iPhone de se délester de l'utilisation mémoire de vues inutilisées.


    dans 1238771795:

    J'ai fait les modifs, mais ça plante quand je souhaite afficher la page, il me sort des erreurs de ce type:

    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x10267b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key R3_btn.'

    As-tu mis R3_btn en property, as-tu mis @synthesize associé ?


    dans 1238771795:

    A quoi doit-on relier le contrôleur de la vue une fois qu'il est définit en outlet dans le xib principal?

    Un contrôleur général ctrlA défini dans le xib principal a une variable d'instance du type IBOutlet qui pointe vers l'instance du contrôleur ctrlB de ta vue dans le xib principal également.
    Dans le xib secondaire, File's Owner représente l'instance ctrlB et les connections de ctrlB avec sa vue, et le contenu de sa vue se configurennt dans ce xib.


    dans 1238771795:

    ps: si tu veux jetter un oeil, j'ai upload le projet modifié, il suffit donc d'aller à  la meme url en mettant "bnk2.zip" à  la place de "bnk.zip".

    Il me semble que tu gagnerais finalement du temps en faisant correctement un petit projet pour chacune des idées présentes dans ce projet (en prévoyant la copie ultérieure des xib et des classes), en les testant à  fond, pour dans un second temps en faire la synthèse dans un projet global dont tu maitriserais mieux l'architecture générale en suite, et où tu t'occuperais de la mise en musique via des navigation ou tabbar ou ... .


     
  • bnkbnk Membre
    23:19 modifié #15
    Oui, je vais faire des petits projets de tabbar avec une seule vue. Un pour chaque idée.

    Pour ceci, il faut que je comprenne comment relier mon UITabBarController avec mon contrôleur de la vue séparé.

    J'ai donc essayé de relier mon contrôleur général (UITabBarController) de mon xib principal avec mon contrôleur secondaire d'un xib séparé ceci sans succès. Je vais donc créer un projet plus simple avec deux controlleurs et deux xib je relie ce que j'ai compris puis je t'enverrai le projet pour que tu fasses la partie concernant la variable d'instance du type IBOutlet pointant vers l'instance du second contrôleur de ma vue principale.

    "Un contrôleur général ctrlA défini dans le xib principal a une variable d'instance du type IBOutlet qui pointe vers l'instance du contrôleur ctrlB de ta vue dans le xib principal également."
  • bnkbnk Membre
    avril 2009 modifié #16
    Bonjour,

    J'ai donc fait un nouveau projet avec un xib principal contenant uniquement mon tabbar controller et un xib secondaire contenant un File's owner du type du controller de la vue (QuizzController).
    Mon controleur du xib secondaire est déclaré comme IBOutlet du controleur de mon xib principal avec un type QuizzController comme suit:

    2444e60c059953c5156f781768f2f.png

    Les images, textView et boutons du xib secondaire ont été reliés au File's Owner après leur avoir attribués les @property et @synthesize.

    Maintenant je ne sais pas exactement comment faire pour pointer l'IBOulet monQuizz vers le File's Owner du xib secondaire.
    voici mon projet: http://*******/beurdel/tabBar.zip

    merci pour l'aide!
  • Philippe49Philippe49 Membre
    23:19 modifié #17
    Premier point :
    Dans question.h et question.m :

    Pas d'accord sur les getReponse :
    1) En Objective-C un getter porte le même nom que la variable, et ta méthode devrait avoir pour signature (=prototype)
            -NSString*) reponse1; :
    En obj-C, [uneQuestion reponse1] c'est la même chose que uneQuestion.reponse1


    2) Le @synthesize fait ce getter à  ta place. Ce n'est que si tu veux faire quelque chose de spécial dans ce getter que tu vas coder cete méthode.

    Pas d'accord avec setMonIntitule non plus, (celui que tu as écrit n'est pas correct au niveau de la gestion mémoire)
    Il faut bien comprendre que @synthesize d'une property génère le code des setter et getter ... plus proprement d'ailleurs puisque la gestion mémoire est alors optimisée (les retain/release).



    Dans question.m, il ne devrait y avoir en fait que dealloc :
    - (void) dealloc {
    [maReponse1 release]
    // ...... et release toutes les properties qui sont en mode retain dans cette classe
    [super dealloc];
    }


  • Philippe49Philippe49 Membre
    avril 2009 modifié #18
    Deuxième Point

    TabBarAppDelegate n'a à  priori pas besoin de l'outlet monQuizzController.


    Dans MainWindow.xib, il faut donner la classe QuizzController à  ce qui est actuellement Selected 'First View Controller'.


    Dans monQuizz.xib connecter l'outlet du File's Owner à  la UIView de plus haut niveau, et supprimer l'autre qui ne sert à  rien.
  • bnkbnk Membre
    avril 2009 modifié #19
    salut Philippe49,

    1. J'ai suivis tes conseils, il est vrai que les set et get écris à  la java faisaient double emplois mais j'ai commencé à  apprendre objC "sur le tas" et j'avais copier un maximum le java le temps de comprendre comment fonctionnaient ces foutus messages (pourtant mon premier langage objet appris était le smalltalk mais ça fait 2 ans et c'est parti loin (oui c'est toujours enseigné!)).

    2.
    Dans monQuizz.xib connecter l'outlet du File's Owner à  la UIView de plus haut niveau, et supprimer l'autre qui ne sert à  rien.

    Je bloque à  cette étape, pourtant je cherche à  éviter de poser des questions cons désolé.

    voici la source mise à  jour: http://*******/beurdel/tabBar2.zip

    3. en deux mots à  quoi sert le first responder?

    edit: voici la vue que j'ai relié (mon appli ne plante plus mais une view vierge est affichée)
    706e7066505670d8b05bec2ec9272.png
  • Philippe49Philippe49 Membre
    23:19 modifié #20
    dans 1238937187:

    edit: voici la vue que j'ai relié (mon appli ne plante plus mais une view vierge est affichée)

    Oui tu as une vue sur ta vue .. et tu ne vois que cette vue qui masque ce qui est derrière

    Voici le xib corrigé
  • Philippe49Philippe49 Membre
    23:19 modifié #21
    dans 1238937187:

    3. en deux mots à  quoi sert le first responder?


    Un UIControl a en général une cible (target) et une action (une méthode de la cible qui est exécutée lors du touch sur le bouton. Par exemple, un de test customButton a pour target File's Owner=QuizzController et une action relancerQuizz

    Lorsque on connecte ce bouton à  firstResponder , on définit seulement la méthode (que l'on rajoute dans le panel IB). Pour l'exécution au runtime, Obj-C va faire l'appel de méthode sur la chaà®ne des objets de type NSResponder inscrit dans la chaà®ne des firstResponder : ici, sans doute
    • envoi au bouton, si il sait y répondre, il y répond sinon il passe la main et
    • envoi à  la superview du bouton, si elle sait y répondre, elle y répond sinon elle passe la main et
    • envoi au viewController de la vue ...
       
  • bnkbnk Membre
    23:19 modifié #22
    Il suffisait juste de relier ceci:
    4b0caeab4ecddbfb50ef0ad6c01f2.png

    c'est bien ca?

    Merci pour tout tes conseils, je vais pouvoir organiser mieux mon projet maintenant.
  • Philippe49Philippe49 Membre
    23:19 modifié #23
    dans 1238946606:

    Il suffisait juste de relier ceci:
    4b0caeab4ecddbfb50ef0ad6c01f2.png

    c'est bien ca?


    Oui, tu te trompais de view à  relier, avec une vue interne inutile.
Connectez-vous ou Inscrivez-vous pour répondre.