[Résolu]Animation : TapGesture dans un UILabel

MarcoDahMarcoDah Membre
avril 2015 modifié dans API UIKit #1

Bonjour à  tous,


 


Je suis actuellement en plein travail sur la gestion de la taille de mes wordings. J'aimerais faire un truc un peu fun. Je pense que c'est déjà  utilisé mais pour une fois plutôt que de trouver des bouts de codes sur le net j'essaye de le faire par moi même. Et donc j'ai subclassé Uilabel.


 


Mon objectif est que si le texte que je désire afficher dépasse 3 lignes sur mon écran alors j'insère un tapGesture qui "déploie" mon label pour afficher avec un effet slide le reste du wording.


 


Mon problème se situe ici. Lorsque je modifie la taille de la frame , lors de l'animation, le label se "recréé" et donc en plus d'augmenté la taille du label, il le "replace" avec une plus grosse hauteur.


 


Je modifie la contrainte hauteur de l'élément et ce n'est pas sa hauteur qui slide mais son " repositionnement".


 


Un tuyau sur une erreur de ma part.


Réponses

  • Salut Marco,


     


    j'ai déjà  essayé de faire des animations avec les UILabel et ça ne marchait pas très bien... Je n'ai pas très bien compris l'animation que tu veux faire, mais comme ça, je te propose comme idée : ne pas changer la frame du label mais masquer (avec un masque) la partie du texte que tu ne veux pas, et animer le mask.


     


    Voilà  un lien qui a l'air intéressant : http://stackoverflow.com/questions/2910770/animating-a-calayers-mask-size-change


  • Merci colas  pour la réponse. Effectivement, je n'y avait pas pensé . Je met ça de côté en attendant d'avoir épuisé toutes les solutions. J'ai réglé mon problème en partie.


     


    La partie ou la frame du label se "repositionne " plus. Mais lors du changement de hauteur ( je modifie la contrainte). Pas d'animation alors que la hauteur se modifie bien.


  • AliGatorAliGator Membre, Modérateur
    mars 2015 modifié #4
    Le "pas d'animation" c'est normal :

    1) Pour les UIView en général, pour animer une contrainte, il ne suffit pas de mettre "constraint.constant = newValue" dans le [UIView animateWithDuration:animation:], c'est pas comme ça que ça marche. Non ce qu'il faut mettre dans le bloc d'animation c'est la ligne de code qui va demander au moteur de AutoLayout de repositionner les éléments en fonction des valeurs des contraintes, pas l'affectation de la valeur de la contrainte :
    self.contraint.constant = kNewValue;
    [UIView animateWithDuration:kDuration animation:^{
    [self.viewToResize setNeedsLayout]; // ou peut-être à  appeler sur self.viewToResize.superview je sais plus
    }];
    Bon c'est le principe général, le vrai code à  appliquer peut se retrouver dans les Programming Guides dédiés, car il est préférable en vrai d'appeler des choses comme setNeedsUpdateConstraints + setNeedsLayout avant de commencer le bloc d'animation, pour s'assurer de le commencer dans un état "stable" où toutes les contraintes précédentes ont déjà  été appliquées, avant de changer ta contrainte à  animer et de n'animer que celle-là . Mais l'important à  comprendre c'est que ça n'animera rien si tu te contentes de mettre le code qui change la valeur de la contrainte dans le bloc d'animation, c'est pas comme ça que marche la logique de AutoLayout.


    2) Mais dans tous les cas tu peux oublier tout ça pour UILabel, car avec UILabel c'est un cas particulier : le relayout du texte lui-même au sein de UILabel ne s'animera jamais pendant l'animation du UILabel.
    Autrement dit, la frame du UILabel lui-même peut changer et s'animer (tu verras l'animation si tu mets par exemple un backgroundColor à  ton UILabel), mais pendant que ton label est animé, le layout du texte (qui décide si un mot doit passer à  la ligne parce que tu arrives au bout de la ligne, etc) n'est pas recalculé avant la fin de l'animation (en même temps ça se comprend, car les calculs pour faire un layout de texte sont un peu coûteux s'ils étaient à  faire à  chaque frame de l'animation).

    Du coup pendant l'animation, même si la frame du UILabel change, le texte qu'il contient ne bouge pas d'un pouce et n'est pas affecté, un peu comme s'il était indépendant de la frame du UILabel qui le contient... et seulement à  la fin de l'animation de la frame du UILabel, alors le layout du texte (disposition des mots pour que ça tienne dans le cadre et passe à  la ligne, etc) est recalculé, pour repositionner/redessiner les mots au bon endroit.

    Ce comportement se voit d'autant + si tu changes une contrainte qui modifie la *largeur* de ton UILabel, par exemple pour le réduire en largeur, pendant l'animation les mots ne vont pas pour autant passer à  la ligne pendant que ça s'anime, mais ne vont être repositionné qu'à  la fin.

    Toi c'est ce qui t'arrive quand tu augmentes la frame de ton label, le texte n'est repositionné / redessiné qu'à  la fin de l'animation donc "l'ouverture de ton label vers le bas" ne fait pas apparaà®tre le texte au fur et à  mesure. Et tu pourras tout essayer, il n'y a pas vraiment de solution en continuant dans cette voie (donc pas la peine de t'épuiser à  tester toutes les solution :P).

    Du coup, puisque tu sais que le texte du label ne sera pas repositionné avant la fin de l'animation et que tu n'y peux rien, il faut utiliser une autre approche, comme celle que t'a proposé colas2, donc d'avoir un label qui fait toute la taille et le mettre en subview d'une UIView qui est plus petite (et c'est elle que tu agrandis).
  • Ok, bon c'est ce que je craignais. J'avais remarqué que quelque chose ne se passait pas comme je le voulais et tu as mis le doigt dessus.


     


    La solution que @colas2 me propose fonctionne je l'ai déjà  mis en place sur d'autre vue de mon appli. Or dans cette vue en particulier je vais faire face à  un empilement trop important et la gestion de la pile de vue risque d'être un peu complexe et me prendra du temps. Temps que je n'ai pas, du coup je laisse comme c'est actuellement.


     


    Merci à  tous pour vos avis et conseil !


Connectez-vous ou Inscrivez-vous pour répondre.