NRGridView

février 2012 modifié dans Actualités #1
Bonjour,



Je vous propose mon premier composant open-source, puisque ma boà®te m'a autorisé à  le rendre comme tel.

NRGridView est une vue en quadrillage qui fonctionne de la même manière que UITableView.. C'est à  dire que les méthodes dataSource & delegate sont quasiment identiques.



Aperçus:

https://github.com/l...l-Landscape.png

https://github.com/l...al-Portrait.png



J'ai effectué ce travail dans le cadre de deux projets pour le groupe Total en France. Sur le coup, il nous servira surtout à  afficher des photos, avec sections.

J'espère aussi que mon travail pourra donner envie à  certaines personnes de rejoindre nos rangs, car nous recherchons encore et toujours des développeurs iOS sur Toulouse image/wink.png' class='bbc_emoticon' alt=';)' /> La boà®te s'appelle Novedia Regions.



NRGridView est disponible sur GitHub




N'hésitez pas à  partager ça autour de vous image/wink.png' class='bbc_emoticon' alt=';)' />

Louka.
«13

Réponses

  • Merci pour ce partage image/wink.png' class='bbc_emoticon' alt=';)' />
  • pas mal, merci!
  • Ca semble être de l'excellent boulot (je ne l'ai pas exécuté, j'ai juste voyagé dans le code).

    Bravo et merci.
  • CéroceCéroce Membre, Modérateur
    Et par rapport à  OHGridView? image/kiss.gif' class='bbc_emoticon' alt=':-*' />
  • muqaddarmuqaddar Administrateur
    J'allais le dire ! image/wink.png' class='bbc_emoticon' alt=';)' />
  • AliGatorAliGator Membre, Modérateur
    J'ai pas regardé le code de Louka (il m'avait prévenu qu'il travaillait sur une classe concurrente) mais je pense que sa classe est plus complète que la mienne, qui n'a pas été maintenue depuis un petit bail (et qu'il faudrait que je révise pour améliorer les performances).

    Donc ça serait à  comparer... mais je pense que de ce qu'il m'a expliqué sa classe est + poussée que la mienne en terme de possibilités ?
  • Voilà , Ali a tout dit.

    ça n'est pas pour faire de l'ombre à  OHGridView.. Laquelle correspond à  d'autres besoins, moins complexe qu'une UITableView.

    NRGridView fonctionne exactement comme UITableView, à  quelques détails près (pas de deletion, accessoryView, ...).

    Le plus par rapport à  OHGridView c'est de pouvoir fonctionner avec des sections comme UITableView.



    Bien sur, le composant évoluera en fonction des besoins de chacun.. Si vous vous donnez la peine de réclamer des fonctionnalités évidemment.

  • muqaddarmuqaddar Administrateur
    février 2012 modifié #9
    Alors, je vais la regarder de plus près dans quelques temps car je maintiens que celle d'Ali a des problèmes de perfs et de sélection de cellules. Je vais sûrement la tester dans 1 ou 2 semaines sur un "vrai" projet, et je te dirai.



    Je suppose qu'on peut setter le nombre de lignes et de colonnes, par section.
  • Merci pour ce partage !



    Petite question



    Dans la méthode suivante


    <br />
    - (void)setBackgroundView:(UIView *)backgroundView<br />
    




    L'ancien _backgroundView n'est pas releasé, c'est normal ?
  • février 2012 modifié #11
    'devulder' a écrit:


    Merci pour ce partage !



    Petite question



    Dans la méthode suivante


    <br />
    - (void)setBackgroundView:(UIView *)backgroundView<br />
    




    L'ancien _backgroundView n'est pas releasé, c'est normal ?




    Non.. Je corrige ça ce soir ! Merci !


    'muqaddar' a écrit:


    Alors, je vais la regarder de plus près dans quelques temps car je maintiens que celle d'Ali a des problèmes de perfs et de sélection de cellules. Je vais sûrement la tester dans 1 ou 2 semaines sur un "vrai" projet, et je te dirai.



    Je suppose qu'on peut setter le nombre de lignes et de colonnes, par section.




    Je doute que celui d'Ali ait un pb de perfs.. bien que je n'ai pas regardé comment c'est foutu.. Mais avec NRGridView, sur un 3GS en utilisant le projet d'exemple (qui contient quand meme beaucoup de cellules visibles à  l'écran, environ 22 au maximum?) ça lag très légèrement.. mais je pense avoir fait mon max tout en essayant de garder un code assez propre... essaie d'imaginer le fait d'afficher 22 lignes à  l'écran avec une UITableView, ça donnera sans doute pareil je pense...

    Il faut savoir que ça dépend aussi de l'optimisation que tu fais de ton côté quand tu rajoutes des trucs la cellule !



    Sinon, non tu ne peux pas choisir le nombre de colones/lignes. En fait ça se fait tout seul comme un grand en fonction du -cellSize que tu auras choisi. Et faut pas être une lumière en maths pour déterminer la taille d'une cellule pour qu'il y en ait, par exemple, 3 par ligne image/wink.png' class='bbc_emoticon' alt=';)' /> Tu mettras un cellSize de 106 de largeur au maximum ou 81 au minimum.
  • muqaddarmuqaddar Administrateur
    Je me doutais de ta réponse, et tu fais comme Ali pour le coup.



    Mais ma question était plutôt de savoir si on pouvait faire une grille de 1 ligne fois X cells mais que seulement 2 cells soient visibles par exemple. Et donc que tu scrolles à  droite pour voir les 10 autres cells non visibles.
  • Bha NRGridView gère le scroll horizontal aussi. Il suffit d'indiquer le layoutStyle... Et encore une fois, pour le nombre de cells ça dépend de la cellSize.
  • muqaddarmuqaddar Administrateur
    Bon j'ai testé en modifant ta Sample App.

    ça a l'air de marcher nikel pour le scroll horizontal.



    Par contre, pas de méthode selectCellAtIndexPath à  ce que je vois ?
  • ça peut se faire. Mais ça fait quoi ? J'ai jamais eu à  faire ça sur une UITableView.. C'est juste pour donner l'apparence "selected" à  la cell que tu veux ça??
  • muqaddarmuqaddar Administrateur
    février 2012 modifié #16
    Oui. C'est plus utile qu'on le croit.

    Imagine une grille de livres sur une étagère: "Montre moi le livre en position D12".



    Si tu ajoutes cette fonction, ta classe sera meilleure que les 3 autres que j'ai déjà  testées... (mets la pression)
  • T'es chier, ça coûte rien a coder image/tongue.png' class='bbc_emoticon' alt=':P' />
  • muqaddarmuqaddar Administrateur
    Alors, fais-le ! Tu connais ta classe, t'en auras pour 20 minutes. image/tongue.png' class='bbc_emoticon' alt=':P' />
  • Faut déjà  que je modifie la méthode -cellAtIndexPath: qui actuellement ne fait pas pareil que UITableView... Enfin je verrai. Je vais p-e gérer une array de selectedCellsIndexPaths
  • AliGatorAliGator Membre, Modérateur
    Sachant que si la cellule n'est pas visible Alex veut que ça scrolle dessus pour la rendre visible image/wink.png' class='bbc_emoticon' alt=';)' />
  • muqaddarmuqaddar Administrateur
    'AliGator' a écrit:


    Sachant que si la cellule n'est pas visible Alex veut que ça scrolle dessus pour la rendre visible image/wink.png' class='bbc_emoticon' alt=';)' />




    ça serait le top !

    Tu n'oublies rien !



    (et donc cette feature n'est pas compatible avec une multi-sélection (ou alors faut faire un choix) ... mais je n'ai pas besoin de la multi sélection)
  • Oui bah pour ça faut effectuer un -scrollRectToVisibleIndexPath: dans ce cas. Je rajouterai ça ce WE
  • C'est bon j'ai mis à  jour.

    J'ai ajouté:
    <br />
    [color=#385789]<br />
    enum[color=#000000]{[/color][/color][color=#cd852e]<br />
    [color=#000000]    NRGridViewScrollPositionNone,   [/color]// Please refer to UITableViewScrollPositionNone&#39;s description.[/color]<br />
        NRGridViewScrollPositionAtTop,<br />
        NRGridViewScrollPositionAtLeft  = NRGridViewScrollPositionAtTop, [color=#cd852e]// for horizontal layout convention[/color]<br />
        NRGridViewScrollPositionAtMiddle,<br />
        NRGridViewScrollPositionAtBottom,<br />
        NRGridViewScrollPositionAtRight = NRGridViewScrollPositionAtBottom [color=#cd852e]// for horizontal layout convention[/color]<br />
    };<br />
    [color=#385789]typedef[/color] NSInteger NRGridViewScrollPosition;<br />
    <br />
    - (void)selectCellAtIndexPath:(NSIndexPath*)indexPath animated:(BOOL)animated;<br />
    - (void)selectCellAtIndexPath:(NSIndexPath*)indexPath autoScroll:(BOOL)autoScroll scrollPosition:(NRGridViewScrollPosition)scrollPosition animated:(BOOL)animated;<br />
    <br />
    - (CGRect)rectForHeaderInSection:(NSInteger)section;<br />
    - (CGRect)rectForSection:(NSInteger)section;<br />
    - (CGRect)rectForItemAtIndexPath:(NSIndexPath*)indexPath;<br />
    <br />
    - (void)scrollRectToSection:(NSInteger)section animated:(BOOL)animated scrollPosition:(NRGridViewScrollPosition)scrollPosition;<br />
    - (void)scrollRectToItemAtIndexPath:(NSIndexPath*)indexPath animated:(BOOL)animated scrollPosition:(NRGridViewScrollPosition)scrollPosition;<br />
    <br />
    
  • muqaddarmuqaddar Administrateur
    Super. image/thumbsup.gif' class='bbc_emoticon' alt='' /> image/thumbsup.gif' class='bbc_emoticon' alt='' /> image/thumbsup.gif' class='bbc_emoticon' alt='' />



    Je teste tout ça la semaine prochaine !
  • CéroceCéroce Membre, Modérateur
    Et pourquoi pas plutôt:


    <br />
    typedef enum{<br />
    	NRGridViewScrollPositionNone,   // Please refer to UITableViewScrollPositionNone&#39;s description.<br />
    	NRGridViewScrollPositionAtTop,<br />
    	NRGridViewScrollPositionAtLeft  = NRGridViewScrollPositionAtTop, // for horizontal layout convention<br />
    	NRGridViewScrollPositionAtMiddle,<br />
    	NRGridViewScrollPositionAtBottom,<br />
    	NRGridViewScrollPositionAtRight = NRGridViewScrollPositionAtBottom // for horizontal layout convention<br />
    } NRGridViewScrollPosition;<br />
    
  • muqaddarmuqaddar Administrateur
    Bon, j'arrive pas à  la faire tourner dans un UIViewController classique avec un Outlet NRGridView, sous-classe de UIScrollView.




    <br />
    - ([color=#b9369d]void[/color])viewDidLoad<br />
    {[color=#3f277d]<br />
    [color=#000000]    [[/color][color=#b9369d]super[/color][color=#000000] [/color]viewDidLoad[color=#000000]];[/color][/color][color=#008123]<br />
    [color=#000000]    [/color]// Do any additional setup after loading the view from its nib.[/color][color=#34595d]<br />
    [color=#000000]  [/color][color=#b9369d]self[/color][color=#000000].[/color][color=#4f8085]gridView[/color][color=#000000] = [[[[/color][color=#4f8085]NRGridView[/color][color=#000000] [/color][color=#3f277d]alloc[/color][color=#000000]] [/color]initWithLayoutStyle[color=#000000]:[/color]NRGridViewLayoutStyleVertical[color=#000000]] [/color][color=#3f277d]autorelease[/color][color=#000000]];[/color][/color][color=#4f8085]<br />
    [color=#000000]  [/color][color=#b9369d]self[/color][color=#000000].[/color]gridView[color=#000000].[/color]delegate[color=#000000] = [/color][color=#b9369d]self[/color][color=#000000];[/color][/color][color=#4f8085]<br />
    [color=#000000]  [/color][color=#b9369d]self[/color][color=#000000].[/color]gridView[color=#000000].[/color]dataSource[color=#000000] = [/color][color=#b9369d]self[/color][color=#000000];    [/color][/color][color=#34595d]<br />
    [color=#000000]  [[[/color][color=#b9369d]self[/color][color=#000000] [/color]gridView[color=#000000]] [/color]setCellSize[color=#000000]:[/color][color=#3f277d]CGSizeMake[/color][color=#000000]([/color][color=#2537d1]160.0[/color][color=#000000], [/color][color=#2537d1]80.0[/color][color=#000000])];[/color][/color][color=#34595d]<br />
    [color=#000000]  [[/color][color=#b9369d]self[/color][color=#000000].[/color][color=#4f8085]gridView[/color][color=#000000] [/color]reloadData[color=#000000]];[/color][/color]<br />
    }<br />
    <br />
    <br />
    - ([color=#6f43a4]NSInteger[/color])numberOfSectionsInGridView:([color=#4f8085]NRGridView[/color] *)gridView<br />
    {[color=#b9369d]<br />
    [color=#000000]  [/color]return[color=#000000] [/color][color=#2537d1]5[/color][color=#000000];[/color][/color]<br />
    }<br />
    <br />
    - ([color=#6f43a4]NSInteger[/color])gridView:([color=#4f8085]NRGridView[/color] *)gridView numberOfItemsInSection:([color=#6f43a4]NSInteger[/color])section<br />
    {[color=#b9369d]<br />
    [color=#000000]  [/color]return[color=#000000] [/color][color=#2537d1]50[/color][color=#000000];[/color][/color]<br />
    }<br />
    <br />
    - ([color=#6f43a4]NSString[/color]*)gridView:([color=#4f8085]NRGridView[/color] *)gridView titleForHeaderInSection:([color=#6f43a4]NSInteger[/color])section<br />
    {<br />
      [color=#b9369d]return[/color] [[color=#6f43a4]NSString[/color] [color=#3f277d]stringWithFormat[/color]:[color=#d1342a]@&quot;Section %i&quot;[/color], section];<br />
    }<br />
    <br />
    <br />
    - ([color=#4f8085]NRGridViewCell[/color]*)gridView:([color=#4f8085]NRGridView[/color] *)aGridView cellForItemAtIndexPath:([color=#6f43a4]NSIndexPath[/color] *)indexPath<br />
    {<br />
      [color=#b9369d]static[/color] [color=#6f43a4]NSString[/color] *MyCellIdentifier = [color=#d1342a]@&quot;MyCellIdentifier&quot;[/color];<br />
      <br />
      [color=#4f8085]NRGridViewCell[/color]* cell = [aGridView [color=#34595d]dequeueReusableCellWithIdentifier[/color]:MyCellIdentifier];<br />
      <br />
      [color=#b9369d]if[/color](cell == [color=#b9369d]nil[/color]){<br />
        cell = [[[[color=#4f8085]NRGridViewCell[/color] [color=#3f277d]alloc[/color]] [color=#34595d]initWithReuseIdentifier[/color]:MyCellIdentifier] [color=#3f277d]autorelease[/color]];<br />
        [color=#3f277d]<br />
    [color=#000000]    [[cell [/color][color=#34595d]textLabel[/color][color=#000000]] [/color]setFont[color=#000000]:[[/color][color=#6f43a4]UIFont[/color][color=#000000] [/color]boldSystemFontOfSize[color=#000000]:[/color][color=#2537d1]11.[/color][color=#000000]]];[/color][/color][color=#3f277d]<br />
    [color=#000000]    [[cell [/color][color=#34595d]detailedTextLabel[/color][color=#000000]] [/color]setFont[color=#000000]:[[/color][color=#6f43a4]UIFont[/color][color=#000000] [/color]systemFontOfSize[color=#000000]:[/color][color=#2537d1]11.[/color][color=#000000]]];[/color][/color]<br />
        <br />
      }<br />
      <br />
      cell.[color=#4f8085]imageView[/color].[color=#6f43a4]image[/color] = [[color=#6f43a4]UIImage[/color] [color=#3f277d]imageNamed[/color]:[[color=#6f43a4]NSString[/color] [color=#3f277d]stringWithFormat[/color]:[color=#d1342a]@&quot;%i.png&quot;[/color], (indexPath.[color=#6f43a4]row[/color]%[color=#2537d1]7[/color])]];<br />
      cell.[color=#4f8085]textLabel[/color].[color=#6f43a4]text[/color] = [[color=#6f43a4]NSString[/color] [color=#3f277d]stringWithFormat[/color]:[color=#d1342a]@&quot;Item %i&quot;[/color], indexPath.[color=#4f8085]itemIndex[/color]];[color=#4f8085]<br />
    [color=#000000]  cell.[/color]detailedTextLabel[color=#000000].[/color][color=#6f43a4]text[/color][color=#000000] = [/color][color=#d1342a]@&quot;Some details&quot;[/color][color=#000000];[/color][/color]<br />
      <br />
      [color=#b9369d]return[/color] cell;<br />
    }<br />
    <br />
    




    Visiblement, il fait des aller-retours entre les méthodes datasource MAIS ne rentre jamais dans la méthode - (NRGridViewCell*)gridView:(NRGridView *)aGridView cellForItemAtIndexPath:(NSIndexPath *)indexPath



    Bizarre, bizarre.
  • février 2012 modifié #27
    ça t'arrives d'assigner une frame ? ^^

    Si tu veux éviter tout ce boulot je te conseille plutôt de faire une sous-classe de NRGridViewController comme il est fait dans l'exemple.
  • muqaddarmuqaddar Administrateur
    février 2012 modifié #28
    'ldesroziers' a écrit:


    Si tu veux éviter tout ce boulot je te conseille plutôt de faire une sous-classe de NRGridViewController comme il est fait dans l'exemple.




    Mouais, et si tu veux un UIViewController qui contrôle une grille NRGridView ET une autre vue UIView par exemple, pourquoi partir sur un NRGridViewController et pas un UIViewController... ce qu'on peut faire avec OHGridView par exemple... ou même avec UITableView. image/kiss.gif' class='bbc_emoticon' alt=':-*' />
  • Mais attend, réfléchi à  ce que tu dis là , il te suffit de foutre une frame.. c'est quoi le problème de faire "myGridView.frame = ..." ??
  • muqaddarmuqaddar Administrateur
    Je l'ai fait marché. Mais il y a des trucs que je ne saisis pas.



    1) Pourquoi tu veux mettre une frame ? La frame est déjà  définie dans le Xib sur la NRGridView héritée de UIScrollView.



    Dans ce cas là , je me contente de ceci qui marche parfaitement:





    - (void)viewDidLoad

    {

    /color][color=#b9369d]super[/color][color=#000000] [/color]viewDidLoad[color=#000000;



    self.gridView.delegate = self;

    self.gridView.dataSource = self;

    [/color][color=#b9369d]self[/color][color=#000000] [/color]gridView[color=#000000 setCellSize:CGSizeMake(176.0, 160.0)];

    }



    2) Maintenant, si on veut personnaliser l'init de la gridView, rien ne marche, même en settant la frame:





    - (void)viewDidLoad

    {

    [super viewDidLoad];



    self.gridView = [[[NRGridView alloc] initWithLayoutStyle:NRGridViewLayoutStyleVertical] autorelease];

    self.gridView.frame = CGRectMake(...);

    self.gridView.delegate = self;

    self.gridView.dataSource = self;

    [[self gridView] setCellSize:CGSizeMake(160.0, 80.0)];



    [self.gridView reloadData];

    }



    Voilà  où je voulais en venir.
  • février 2012 modifié #31
    Tu ne réfléchis pas assez je te dis.

    1) Vérifie la frame de self.view

    2) N'oublie pas de foutre un auto-resizing mask à  la gridView!!.



    Rien n'indique qu'au moment du viewDidLoad, la frame de self.view est la frame finale.

    Si tu veux faire un bon layout, il te faut une méthode privée du genre "__layoutContent", comme fait UINavigationController pour bien replacer la navBar + viewController.view active.



    En gros:
    <br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]- (void)viewDidLoad[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]{[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3][super viewDidLoad];[/size][/font][/color]<br />
    <br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]self.gridView = [[[NRGridView alloc] initWithLayoutStyle:NRGridViewLayoutStyleVertical] autorelease];[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]self.gridView.frame = [self.view bounds];[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]self.gridView.delegate = self;[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]self.gridView.dataSource = self; [/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]self.gridView.autoresizingMask = ([/size][/font][/color]UIViewAutoresizingFlexibleWidth[color=#282828][font=helvetica, arial, sans-serif][size=3]|[/size][/font][/color]UIViewAutoresizingFlexibleHeight);<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3][[self gridView] setCellSize:CGSizeMake(160.0, 80.0)];[/size][/font][/color]<br />
    <br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3][self.gridView reloadData];[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]}[/size][/font][/color]<br />
    [color=#282828][font=helvetica, arial, sans-serif][size=3]
    
    [/size][/font][/color]



    [font=helvetica, arial, sans-serif]Là  c'est le cas où la gridView prend toute la vue. Sinon il va vraiment falloir faire un __layoutContent ou un truc du genre, car rien ne dit que ta vue ne va pas démarrer avec une frame CGRectZero, pour ensuite être élargie automatiquement par son parentViewController (si il y a.)[/font]

    [font=helvetica, arial, sans-serif]D'ailleurs tu ne devrais meme pas faire ça au viewDidLoad, mais au loadView, c'est plus clean de mon point de vue.[/font]

    [font=helvetica, arial, sans-serif]Tu noteras que ça marche très bien depuis NRGridViewController (regarde le code), qui lui n'utilise pas de xib. Certes ça utilise -setView: mais il n'empêche que ça fonctionne. C'est juste que tu ne dois pas avoir l'habitude de gérer plusieurs vues manuellement dans une seule comme le fait UINavigationController et ses consoeurs.[/font]

    [font=helvetica, arial, sans-serif]Sauf si, bien entendu, tu démarres avec un xib, où là  a déjà  une frame assez "conséquente" pour pouvoir placer tes éléments au moment où la vue se charge. Sans oublier un autoresizing mask évidemment image/wink.png' class='bbc_emoticon' alt=';)' />[/font]

    [font=helvetica, arial, sans-serif]Par contre, p-e que UITableView démarre avec un autoresizingMask flexible width/height par défaut, je ne sais pas.. Moi j'en ai pas mis par défaut sur ma NRGridView [/font]
Connectez-vous ou Inscrivez-vous pour répondre.