Comment gérer une vue personnalisée?

GreensourceGreensource Membre
février 2009 modifié dans API UIKit #1
Bonjour, je vais essayer d'être précis et concis ;)
je souhaiterais créer une "case". C'est à  dire que j'ai besoin d'une représentation graphique de celle-ci et de divers méthodes et attributs.
Ma première idée, qui me semble être mauvais étais de faire hérité ma case de NSView.
Mais finalement, il me semble que le mieux est de faire:
-Une Vue personnalisé: NSView,CAlayer...je ne sais pas trop
-Un controlleur de vue personnalisé
-Et enfin un objet case avec tout le code métier.
Suis-je sur la bonne voie? Connaitriez-vous des tuto sur comment faire une vue personnalisée? La mienne doit être hexagonale avec des informations textuelle au centre.
Merci
«1

Réponses

  • schlumschlum Membre
    16:18 modifié #2
    Il en faut une ou plusieurs accolées genre damier hexagonal ?
  • GreensourceGreensource Membre
    février 2009 modifié #3
    Je voudrais en effet une sorte de damier hexagonal.
    Pour l'instant je vais faire plus simple, je vais me cantonner à  7 cases. Plus tard je voudrais que le damier n'est pas une taille prédéfinie.

    Seulement j'ai un souci. J'ai fait un Projet View-Based Application. Au départ on a un contrôleur de la vue principale. Maintenant je suppose qu'il me faut un contrôleur par vue de case? Mais je n'ai aucune idée de comment lié les contrôleurs ensemble.

    Par exemple pour l'instant j'ai une seule case et un seul contrôleur(GWCaseController) pour cette case en plus du contrôleur de la vue principale. Dans IB j'ajoute une vue, je met une image hexagonale dedans. Je lie cette vue à  un IBOutlet du contrôleur de ma vue de case(GWCaseController).
    Puis dans mon implémentation de ce contrôleur j'ajoute la méthode:
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    et j'écris un truc dans la console.
    Et puis valà , je me disais chouette tout ira bien, mais non, si je clic dans l'hexagone -> rien ne se passe et si je clic en dehors --> Erreur d'adresse!
    Je vois bien que je ne fait pas ce qu'il faut mais je galère à  trouver des examples qui explique ça.
    Merci de m'aider... :(

    [edit] Je crois avoir compris quelques choses. Un contrôleur de vue est utiliser pour la vue principale uniquement (la grande qui prend tout l'iPhone) Et sinon toute les vue dedans sont gérer par ce contrôleur. Donc moi ma case doit être un IBOutlet du contrôleur de la vue principale c'est bien ça?
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #4
    Pour ton cas surtout le fait que tes cellules soient hexagonales, moi je ferais plutôt tout dans une seule vue (tout ton plateau). D'autant que si tes cases hexagonales sont sensées être accolées, leurs rectangles englobants vont se chevaucher or c'est ce qu'il faut éviter à  tout prix ;)

    Tu peux bien sûr avoir une classe "Case" mais qui ne sera pas vraiment être une vue, plutôt contenir les informations sur ta case, et le BezierPath associé qui va définir les contours de ta case.
    C'est comme ça que j'ai fait pour un jeu iPhone que j'ai commencé : dans ta classe Case tu peux par exemple stocker un CGMutablePathRef (équivalent iPhone d'un NSBezierPath "modifiable") représentant ton hexagone à  dessiner, avec sa position (x,y)... et tu peux avoir une méthode qui teste si un CGPoint est dans ta "case" (avec [tt]CGPathContainsPoint[/tt]), etc... et une methode [tt]draw[/tt] qui consiste à  dessiner ta cellule (dans le contexte graphique actuel) en appelant [tt]CGContextDrawPath[/tt].

    Une fois que tu as tout ça, pour dessiner ton plateau, il te suffit alors d'une UIView qui, dans sa méthode drawRect, parcourt tous tes objets "Case" (instances de Case que tu auras mis dans un NSArray par exemple) et appelle dessus [maCase draw] sur chacun pour dessiner chacune des cases sur ton plateau.
  • schlumschlum Membre
    16:18 modifié #5
    dans 1235328689:

    Pour ton cas surtout le fait que tes cellules soient hexagonales, moi je ferais plutôt tout dans une seule vue (tout ton plateau). D'autant que si tes cases hexagonales sont sensées être accolées, leurs rectangles englobants vont se chevaucher or c'est ce qu'il faut éviter à  tout prix ;)


    +1
    à‰vite de faire une vue par case...
    Et puis vue et contrôleur sont censés être indépendants ; tu peux avoir un contrôleur par case et une vue qui gère le tout.
  • GreensourceGreensource Membre
    16:18 modifié #6
    Hum..ok je crois mieux comprendre comment je doit faire. Donc pour moi il vaudrait mieux avoir un controlleur par case (puisqu'elle vont devoir repondre aux clics) et un controlleur de vue plateau qui contiendrais une arraylist de case?
    Merci pour ces infos en tout cas!
  • schlumschlum Membre
    16:18 modifié #7
    La réponse aux clics fait partie de la vue.
    La vue qui est un NSResponder doit récupérer les clics, calculer dans quelle case elle est et dispatcher les événements en fonction de ses calculs.
  • GreensourceGreensource Membre
    16:18 modifié #8
    dans 1235381691:

    La vue qui est un NSResponder doit récupérer les clics, calculer dans quelle case elle est et dispatcher les événements en fonction de ses calculs.

    Mais je ne comprend pas vraiment comment le système va savoir à  qu'elle case il doit s'adressé? Enfin si je comprend bien qu'avec les coordonnées il va savoir, mais ma case doit bien être un UIControl pour pouvoir réagir au "stimuli" externe?
  • schlumschlum Membre
    16:18 modifié #9
    dans 1235404761:

    dans 1235381691:

    La vue qui est un NSResponder doit récupérer les clics, calculer dans quelle case elle est et dispatcher les événements en fonction de ses calculs.

    Mais je ne comprend pas vraiment comment le système va savoir à  qu'elle case il doit s'adressé? Enfin si je comprend bien qu'avec les coordonnées il va savoir, mais ma case doit bien être un UIControl pour pouvoir réagir au "stimuli" externe?


    Tous les Responders sont capables de réagir aux " stimulis "... dont les vues.
  • GreensourceGreensource Membre
    février 2009 modifié #10
    Autant pour moi, je n'avais pas vu que UIView héritait de UIResponder.
    Donc pour moi, ma case sera une UIView. Je vais essayer de bien réfléchir à  mon truc parce qu'il me semble que je dois découpler vue et model de ma case, donc il me faut bien, une vue case, un controller pour ma case ainsi que le model.

    J'ai l'impression que mon esprit tourne en rond et mélange plein de truc! :o C'est pas trop évident le MVC n'empêche! Ca ira sûrement mieux une fois que j'aurais fait ma première vrai implémentation.

    Merki!

    [edit]
    dans 1235328689:

    dans ta classe Case tu peux par exemple stocker un CGMutablePathRef (équivalent iPhone d'un NSBezierPath "modifiable")

    Je viens de regarder un peu la doc, je suis un peu perdu du coup car le CGMutablePathRef est un type opaque visiblement alors que NSBezierPath étais une class, donc j'avoue ne pas trop comprendre en quoi ça peut être l'équivalent? Ya pas de méthode pour dessiner dans CGMutablePathRef, si?
  • Philippe49Philippe49 Membre
    16:18 modifié #11
    dans 1235408058:

    Je viens de regarder un peu la doc, je suis un peu perdu du coup car le CGMutablePathRef est un type opaque visiblement alors que NSBezierPath étais une class, donc j'avoue ne pas trop comprendre en quoi ça peut être l'équivalent? Ya pas de méthode pour dessiner dans CGMutablePathRef, si?


    dans drawRectangle
    CGContextRef context=UIGraphicsGetCurrentContext();
    [[UIColor redColor] set];
    CGContextFillRect(context, rect);

    Voir ensuite la doc CGPathRef
  • schlumschlum Membre
    16:18 modifié #12
    CG c'est une API C... pas de classes ni de méthodes.
    Mais c'est complètement équivalent quand même... NSBezierPath est un wrapper au dessus de CGPath
  • GreensourceGreensource Membre
    16:18 modifié #13
    Oulalala, je suis pommé de chez pommé là  :-\\. Je suis vraiment désoler mais j'ai un niveau très moyen (pour ne pas dire mauvais) en C. Et l'Objective-C je m'y suis mis avec Cocoa par la pratique, c'est en cours...Je viens de Java et encore je n'ai plus ou moins fait que des TP donc bon.
    Je pensais me faire un autre bouquin sur iPhone plus spécifiquement par ce que là  je sens qu'il me manque des bases quand même (si vous avez une bonne référence...)
    Je vais allez voir les tuto qui sont ici aussi.

    Merci bien en tout cas, je vais essayer de comprendre ce que vous me dites  ;)
  • schlumschlum Membre
    16:18 modifié #14
    Vouloir faire de la programmation iPhone sans bien connaà®tre le C c'est assez illusoire...
    Puis le C c'est la base de l'Objective-C, du C++, du C#, voire même du Java hein.

    http://www.siteduzero.com/tutoriel-3-14189-apprenez-a-programmer-en-c.html
  • GreensourceGreensource Membre
    16:18 modifié #15
    Nan mais si tu veux les bases du C,C++ Objective-C je crois en avoir acquise une bonne partie, j'ai fait des tuto, j'ai eu des cours dessus, maintenant ce qu'il me manque c'est essentiellement de la pratique je pense. D'où mon petit projet que j'essaie de monter.
    Le principal souci que j'ai c'est que les outils pour iPhone/Mac me sont encore inconnu, et je vais pas poser une question ici à  chaque fois que je ne connais pas quelques choses, vous allez vite en avoir marre  :P
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #16
    Bah je t'ai tout expliqué dans ma réponse plus haut :
    - Une classe case pour représenter tes cases, dans lequel tu peux avoir un CGPath de stocké représentant ton hexagone, et, en utilisant les méthodes de CGPath que je t'ai mentionné, tu peux alors testé si un point (typiquement coordonnées d'un clic dans ton plateau) est dans ta case hexagonale ou pas
    - Une vue représentant ton plateau, et contenant un NSArray de cases... Et dans le drawRect de ta vue, tu parcoures ton NSArray de cases, et demande à  chacune de se dessiner. Tu n'auras bien qu'une seule vue, celle de ton plateau, mais plutôt que ton plateau dessine chacune des cases, tes classes cases (qui sont juste des classes représentant les cases côté modèle en fait, descendant de NSObject, ce n'est pas des UIView) dessineront chacune un hexagone à  la bonne position dans ta vue unique "Plateau"
    - Quand tu cliques dans ton plateau, tu parcoures ton NSArray de cases encore, mais cette fois pour demander à  chacune si le clic est contenu dans le CGPath de la case ou pas.... dès que tu trouves la case qui te dit que ton clic est dedans, tu sais que c'est la case cliquée et tu peux agir en conséquence.
  • GreensourceGreensource Membre
    16:18 modifié #17
    Ok je comprend mieux.
    J'ai fait ma case, elle hérite de NSObject. Elle a un attribut CGPathRef et une méthode draw.
    J'ai aussi fait une vue plateau qui hérite de UIView et qui contient pour l'instant ne seule Case.
    -Premier truc bizarre, quand je lance l'appli, la méthode initWithFrame du plateau n'est pas appelé, c'est drawRect qui est appelé ??? C'est pas pratique du tout pour initialiser ma case.
    Et donc dans drawRect j'initialise la case et j'appelle draw dessus.
    Tout ça marche bien, je te remercie!
    Je vais maintenant essayer de faire un beau dessin d'hexagone ^^
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #18
    initWithFrame n'est appelé que si tu initialises ton objet par code. S'il est créé suite à  un "désarchivage de NIB" (tu as créé ta vue de plateau dans InterfaceBuilder dans un fichier .xib quoi), c'est awakeFromNib qui est appelé à  la place.
  • GreensourceGreensource Membre
    février 2009 modifié #19
    Ah oui c'est vrai, j'avais oublier! Merci encore, c'est cool je commence à  me dépatouiller de tout ça! Merci beaucoup! :adios!:

    [edit] Voilà  ce que j'ai réussi à  faire:
    picture2.th.png

    Bon j'ai un peu tricher, pour l'instant de dessine tout dans la méthode draw de ma case, je n'utilise pas CGPathRef  ::)
  • AliGatorAliGator Membre, Modérateur
    février 2009 modifié #20
    J'ai repris/extrait mon code de ma petite appli de jeu pour ma part, et l'ai adapté à  ton cas de cellules hexagonales.

    Voilà  ce que ça donne pour moi :

    (1) une classe HXCell qui décrit une cellule initialisée une position X/Y, une taille (commune à  toutes les cellules en fait) et un "tag" (un nombre que j'affiche sur la cellule juste pour l'exemple pour différencier les cellules et être sûr que je détecte le clic sur la bonne etc).
    Chaque cellule [tt]HXCell[/tt] a en plus des variables d'instance comme un booléen pour indiquer le mode "sélectionnée" ou pas, ainsi sa couleur de contour et sa couleur de remplissage quand elle est sélectionnée, ou non.
    Ces HXCell ont une méthode [tt]draw[/tt] pour se dessiner dans le contexte graphique courant, avec les couleurs adéquates, et une méthode [tt]containsPoint:[/tt] qui dit si oui on non un point est contenu dans la cellule ou pas, utile pour le picking lors d'un "touch" (voir plus bas).

    (2) Une classe HXBoardView, héritant de [tt]UIView[/tt], qui en fait est la vue principale de mon appli (j'ai modifié sa classe dans le XIB depuis InterfaceBuilder). Cette classe a une méthode [tt]initCells[/tt] (appellée par [tt]initWithFrame[/tt] et [tt]awakeFromNib[/tt] comme ça on est tranquille) qui remplit un tableau de HXCells, la méthode [tt]drawRect[/tt] qui dessine chacune de ces HXCells, et une méthode [tt]cellAtPoint:[/tt] qui retourne la HXCell qui est "sous" le CGPoint donné (méthode utilisée lors du picking donc) en faisant appel à  [tt]containsPoint:[/tt] de chacune des HXCells jusqu'à  trouver la bonne.


    Ensuite quand on appelle [tt]touchBegan[/tt] dans ma HXBoardView, j'ai plus qu'à  appeller [tt]cellAtPoint[/tt] pour savoir la cellule cliquée, je met son attribut "selected" à  YES et je dis à  ma vue qu'il faut qu'elle se redessine. et dans le [tt]touchEnded[/tt], je remet le "selected" de la cellule précédemment cliquée à  NO.


    Voilà , je te laisse regarder et exécuter le projet (fourni dans HexaCells.zip) pour te donner une idée de tout ça. Du coup quand tu cliques sur ton écran d'iPhone, tu verras la cellule cliquée se mettre en bleu, ce qui illustre que le picking de la cellule cliquée fonctionne bien.
    NB : Je n'ai créé que les deux classes HXCell et HXBoardView, je n'ai pas touché aux autres (qui ont été créés par Xcode quand j'ai créé ce nouveau projet)
  • schlumschlum Membre
    16:18 modifié #21
    dans 1235428660:

    initWithFrame n'est appelé que si tu initialises ton objet par code. S'il est créé suite à  un "désarchivage de NIB" (tu as créé ta vue de plateau dans InterfaceBuilder dans un fichier .xib quoi), c'est awakeFromNib qui est appelé à  la place.


    En fait, "awakeFromNib" n'est pas vraiment le pendant de "initWithFrame"...
    Le "init" à  partir d'un .nib, c'est "initWithCoder" (un .nib, c'est de l'archivage en utilisant <NSCoding>)

    Par contre, "awakeFromNib" est intéressant dans le fait qu'il est appelé une fois que tous les objets du .nib sont chargés. On peut donc agir sur ces objets...
  • MalaMala Membre, Modérateur
    16:18 modifié #22
    dans 1235440612:

    " Dernière édition: Aujourd'hui à  03:06 par AliGator "

    3:06 C'est du propre!  :fouf):
  • GreensourceGreensource Membre
    16:18 modifié #23
    He ben! Je crois que je te dois un grand grand merci! C'est vraiment super sympa ce que tu fait! Maintenant je comprend exactement ce qu'il faut que je fasse! Ton code est super, bien commenter et tout, nickel!
    Vraiment je te remercie  o:) o:) o:) o:) o:)
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #24
    dans 1235465657:

    En fait, "awakeFromNib" n'est pas vraiment le pendant de "initWithFrame"...
    Le "init" à  partir d'un .nib, c'est "initWithCoder" (un .nib, c'est de l'archivage en utilisant <NSCoding>)

    Par contre, "awakeFromNib" est intéressant dans le fait qu'il est appelé une fois que tous les objets du .nib sont chargés. On peut donc agir sur ces objets...
    Ah oui c'est vrai ça, c'est pas idiot comme remarque ! J'aurais dû appeler du coup mon initCells dans initWithFrame et... dans initWithCoder et non awakeFromNib, ça aurait été plus cohérent du coup.

    Merci de ce rappel car j'ai c'est vrai que j'ai un peu pris l'habitude de cette pratique (appeler une méthode perso dans initWithFrame et awakeFromNib pour que ça marche que ma classe soit créée par code ou par NIB) mais tu me fais réaliser que ce n'est pas la bonne méthode que j'utilisais pour le 2e cas ;)

    --

    Greensource : ma méthode n'est pas la seule possible, ce n'est qu'un exemple. J'aurais pu aussi (ça aurait peut-être été plus intelligent d'ailleurs ?) ne pas stocker le CGMutablePathRef dans ma classe HXCell vu que les cellules ont toutes la même forme hexagonale : j'ai repris cette idée d'un jeu à  moi (sorte de puzzle) où chaque pièce avait une forme différente, d'où l'idée d'un path différent par pièce... Mais dans ton cas tu aurais pu aussi te servir d'une classe HXCell juste pour mémoriser la position des cellules, leur tag, un delegate éventuellement, ce gnre de petit détail qui différencie chaque cellule quoi, un peu plus orienté "modèle" que vue du coup... Et stocker un unque CGPath dans la classe HXBoardView. Et au moment du dessin, tu boucles sur chaque HXCell, tu appliques une CGAffineTransform pour te placer à  la position stockée dans ta HXCell, mais c'est HXBoardView qui ajoute le CGPath au contexte graphique puis le dessine. Comme ça tu n'as qu'un seul CGPahRef représentant un hexagone, c'est ta vue qui le dessine, et tes HXCells ne servent qu'à  mémoriser les données de positionnement à  appliquer lors du dessin desdites cellules. Enfin c'est juste une autre possibilité quoi.
  • GreensourceGreensource Membre
    16:18 modifié #25
    Oui, c'est pas faux, je vais y réfléchir. Il y a aussi une autre chose qui me chiffonne un peu. C'est de stocker une liste de case dans la vue du plateau. Ca ne devrais pas être stocker dans le model du plateau plutôt si on veut respecter le MVC?
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #26
    C'est pas idiot du tout comme remarque.
    En fait je pense que la solution idéale pour faire proprement MVC c'est :

    1) Stocker tes cases dans le modèle en effet. Ces cases ne comporteraient que les statuts de tes cases, genre sélectionné ou pas, position sur la grille (en terme de "pas", comme je l'ai fait pour mon initWithPositionX:Y: où j'ai pas mis la position en pixels mais en position sur la grille), par exemple

    2) Côté vue, tu n'aurais que ton plateau, qui va stocker un unique CGPath représentant un hexagone, et les constantes propres au dessin : couleur de contour, couleur de remplissage quand sélectionné ou pas, taille de la "grille" (équivalent de mon "scale" dans mon projet), etc...

    3) Et quand il a besoin de dessiner, il demande au modèle que celui-ci lui retourne le nombre de cellules, et chacune des cellules (prend exemple sur le modèle du DataSource utilisé pour les TableView par exemple), comme ça il peut boucler sur chacune des "cases" de ton modèle et leur demander leur position sur la grille... en multipliant par ton "scale" (ton pas de grille) en X et en Y, ça te donne la CGAffineTransform (translation) à  appliquer avant de dessiner ton CGPath hexagonal

    4) De même pour le picking, tu demande à  ton "dataSource" (ton modèle) qu'il te donne le nombre de cellules et boucle sur chacune d'elle en demandant au modèle la cellule numéro N, et teste alors chacune pour savoir si le clic est dedans.

    Au moins là  en effet tu sépares mieux Vue et Modèle, avec ton plateau qui ne s'occupe que de la vue (et de la détection de clic pour informer le modèle ensuite quelle cellule a été cliquée) et ton modèle qui fournit les informations genre position de chaque cellule, aspect sélectionné ou non, et tout ce qui a attraà®t au reste de ton jeu (valeur de la case ou que sais-je encore)
  • GreensourceGreensource Membre
    16:18 modifié #27
    Ouais j'imaginais quelque chose dans ce style en effet. J'essaie de mettre ça en place demain et je te redis.
  • GreensourceGreensource Membre
    16:18 modifié #28
    Sinon j'avais une ou deux question par rapport à  ton code:
    Ya t'il une raison au fait que tu utilises self ici:
    self.tag = aTag;<br />self.strokeColor = [UIColor blackColor];<br />self.fillColor = [UIColor whiteColor];<br />self.selectedFillColor = [UIColor blueColor];
    

    Il me semblais que c'était beaucoup moins rapide de passer par les accesseurs?

    Ah oui et ici aussi:
    // position translatée au centre de la vue<br />CGPoint trPos = CGPointMake(pos.x - self.bounds.size.width/2, pos.y - self.bounds.size.height/2);<br />	for(GWCase* c in e)<br />	{<br />		if ([c containsPoint:trPos]) return c;<br />	}
    

    j'avoue là  je capte pas du tout ce que ça fait.
    Tu soustrais aux coordonnée de ta cellule, la moitié de la taille de la vue c'est bien ça? Je vois bien que ça marche ce que tu fais mais c'est de la magie là  pour moi ^^
  • AliGatorAliGator Membre, Modérateur
    16:18 modifié #29
    Alors pour le coup des accesseurs, c'est parce que j'en ai pris l'habitude pour être sûr que les setter/getters sont bien appelés car parfois ils ne font pas grand chose et autant ne pas mettre le "self." devant pour accéder directement à  la variable d'instance... mais des fois ils font un peu plus.
    En l'occurrence si je ne mettais pas "[tt]self.fillColor = ...[/tt]" il faudrait quand même que je pense alors à  appeler le retain sur la variable ([tt]fillColor = [[UIColor whiteColor] retain];[/tt]) pour rester cohérent avec l'attribut "retain" que j'ai mis dans mon @property correspondant... Et si je décide un jour de changer ce [tt]@property(retain) UIColor* fillColor[/tt], pour une raison quelconque, en [tt]@property(copy)[/tt] ou [tt]@property(assign)[/tt] il faudra que je pense à  adapter mon code en conséquence.

    Alors qu'en faisant appel à  self.fillColor et donc implicitement au setter, pas de soucis, je sais que tout restera toujours cohérent. C'est pas pour le temps ridicule et infime que potentiellement ça fait perdre au programme, et puis c'est pas comme s'il y avait nécessité d'une appli temps réel ou que c'était fait 500 fois dans une boucle :P

    --

    D'ailleurs dans le projet que je t'ai filé, il y a une coquille : dans le [tt]-(void)dealloc[/tt] justement j'ai mis [tt]fillColor : nil[/tt] (ce qui n'a pas grand intérêt en soit) alors que j'aurais dû mettre [tt]self.fillColor = nil;[/tt] qui lui a pour effet d'appeler implicitement le setter qui va faire un "release" sur la UIColor précédemment stockée dans fillColor (avant de faire un retain sur la nouvelle valeur, qui vaut nil en l'occurrence, donc ça n'aura aucun effet), ce qui permet donc de respecter l'équilibre retain/release. Et j'ai oublié d'ajouter le code équivalent pour strokeColor et selectedFillColor dans ce même dealloc.
    Si tu lances Clang GUI sur le projet pour tester les risques d'erreurs de prog, tu verras d'ailleurs qu'il te signale que j'ai oublié tout ça.
  • AliGatorAliGator Membre, Modérateur
    février 2009 modifié #30
    dans 1235561068:

    Ah oui et ici aussi:
    // position translatée au centre de la vue<br />CGPoint trPos = CGPointMake(pos.x - self.bounds.size.width/2, pos.y - self.bounds.size.height/2);<br />	for(GWCase* c in e)<br />	{<br />		if ([c containsPoint:trPos]) return c;<br />	}
    

    j'avoue là  je capte pas du tout ce que ça fait.
    Tu soustrais aux coordonnée de ta cellule, la moitié de la taille de la vue c'est bien ça? Je vois bien que ça marche ce que tu fais mais c'est de la magie là  pour moi ^^
    Bah en fait c'est simple. L'origine des coordonnées sur iPhone est en haut à  gauche de la vue, X positifs vers la droite et Y positifs vers le bas. Moi ça m'arrangeait pas, je préfère raisonner avec le (0,0) en plein centre de ma vue. C'est tout. Donc je corrige mes coordonnées ;)

    Quand je dessine mes cases, tu remarqueras qu'avant de dessiner mes cases je fait une transformation affine qui est justement une translation de la moitié de la taille de la vue... autrement dit je place le (0,0) qui était en haut à  gauche pour qu'il tombe au centre de ma vue. Du coup le coint supérieur gauche devient pour moi non plus (0,0) mais (-W/2,-H/2)... et le coin en bas à  droite n'est plus (W,H) mais (W/2,H/2).
    Et du coup quand dans cette méthode je veux détecter dans quelle vue est un point donné, ce point étant donné dans les coordonnées de la vue il faut que je le ramène dans mon système de coordonnées où j'ai mis l'origine au centre de ma vue ! Donc si je clique au centre, il va me dire que j'ai cliqué en (W/2,H/2) alors que pour moi c'est (0,0)... d'où la soustraction effectuée sur ces coordonnées avant de tester avec les coordonnées des cases, qui elles sont dessinées en partant du principe que le (0,0) est au centre.
  • GreensourceGreensource Membre
    février 2009 modifié #31
    Ahhhhh ok ok, je comprend maintenant! Je trouvais ça trop bizarre parce qu'effectivement j'avais lu dans la donc que l'origine étais en haut à  gauche et du coup je captais pas les coordonnées négative de tes cases.
    Et bien merci encore! Tiens tu l'as bien mérité:  :p
Connectez-vous ou Inscrivez-vous pour répondre.