[Obj-C] Changer l'image d'un bouton empêche le changement de position de ce dernier

Hello,


 


Voila j'ai fait un code permettant de changer la position d'un bouton (ainsi que la taille de 2 vues).


 


Tout marche très bien si je ne change pas l'image du bouton. Si néanmoins je la change, rien ne change (ni la taille des 2 vues, ni la position du bouton).


 


Voila le code que j'utilise :`



- (void) extandView
{
[UIView animateWithDuration:1.0
delay:0.2
options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
if(isViewExpanded == 0)
{
view1.frame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height + heightTobeExpanded);

expandButton.frame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y + heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height);

view2.frame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y + heightTobeExpanded, view2.frame.size.width, view2.frame.size.height - heightTobeExpanded);


//[expandButton setImage:[UIImage imageNamed:@arrow-top.png] forState:UIControlStateNormal];
isViewExpanded = 1;
}
else if(isViewExpanded == 1)
{
view1.frame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height - heightTobeExpanded);

expandButton.frame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y - heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height );

view2.frame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y - heightTobeExpanded, view2.frame.size.width, view2.frame.size.height + heightTobeExpanded);


//[expandButton setImage:[UIImage imageNamed:@arrow-bottom.png] forState:UIControlStateNormal];
isViewExpanded = 0;
}
}
completion:nil];


}


Avez vous une idée de comment faire svp ? Merci d'avance :D


Réponses

  • CéroceCéroce Membre, Modérateur
    janvier 2016 modifié #2
    C'est effectivement étrange. Changer l'image peut éventuellement appeler -setFrame: sur le bouton. Par contre, je ne saisis pas pourquoi ça interviendrait sur les autres vues.
    As-tu essayé de fixer l'image _d'abord_ ?
    N'aurais-tu pas des contraintes auto-layout entre les vues et le bouton ?
  • Ben77650Ben77650 Membre
    janvier 2016 modifié #3


    C'est effectivement étrange. Changer l'image peut éventuellement appeler -setFrame: sur le bouton. Par contre, je ne saisis pas pourquoi ça interviendrait sur les autres vues.

    As-tu essayé de fixer l'image _d'abord_ ?

    N'aurais-tu pas des contraintes auto-layout entre les vues et le bouton ?




     


    Hello Céroce,


     


    Non je n'ai pas de contraintes auto-layout, c'est un projet test que j'ai crée pour appréhender le fonctionnement de cette vue extensible.


     


    C'est d'autant plus bizarre que j'ai essayé de changer l'image a différents moments / endroits :


    - Au début de mon if


    - Au milieu du if


    - A la fin du if


    - A l'extérieur du callback


    - Dans une méthode externe


     


    J'ai même essayé de la mettre en tant que BackgroundImage, mais le problème persiste.


     


    L'image est fixé au lancement de l'application comme étant "arrow-bottom" et devrait changer au clic.


     


    Voila quelques screens de mon application:


     


     


    Comportement attendu (mais avec une flèche pointant vers le haut dans la 2e image) : 


    539198Capturedecran20160119a100842.png(image 1)554616Capturedecran20160119a100858.png(image 2)


     


    Comportement actuel :


    539198Capturedecran20160119a100842.png(image 1)161949Capturedecran20160119a100923.png(image 3)


     


    La chose relativement bizarre est que dans le comportement actuel, c'est que lors de l'animation il part bien de la position "attendue" (image 2), et remonte jusqu'à  la position "normale" (image 1)


  • Et si tu traces ton code à  l'exécution, il n'y a rien d'anormal ?

  • Ben77650Ben77650 Membre
    janvier 2016 modifié #5

    C'est extrêmement bizarre cette histoire.


     


    Je viens de faire un NSLog dans mon if et dans mon else



    NSLog(@Origin %f, expandButton.frame.origin.y);

    Dans le 1er cas ou il est dans if il est égal à  63, et dans le cas ou il est dans le else il est égal à  303 (mais s'affiche visiblement en 63).


     


    J'y comprends rien à  cette histoire, et mes collègues (dont le Directeur Technique) non plus.


  • Pour ceux qui souhaitent voir le projet, vous le trouverez en pièce jointe


  • Si tu fais la même chose en dehors d'une animation, j'imagine qu'il n'y a pas de problème, non ?




  • Si tu fais la même chose en dehors d'une animation, j'imagine qu'il n'y a pas de problème, non ?




     


    Justement si, j'ai essayé de le mettre en dehors de l'animation (et j'ai même essayé de le mettre dans une méthode externe) et il y a toujours ce fameux problème :/

  • Si tu disables l'autolayout dans ton storyboard, cela marche...


     


    Tu perds le SizeClass du coup, donc je pense qu'il faudrait garder l'autolayout, mais potentiellement jouer sur les valeurs de ces dernières pour l'animation plutôt que tu les frames directement...


    Car des p'tits top/left/width/height seront générées automatiquement.




  • Je pense qu'il faudrait garder l'autolayout, mais potentiellement jouer sur les valeurs de ces dernières pour l'animation plutôt que tu les frames directement...


    Car des p'tits top/left/width/height seront générées automatiquement.




     


    Et ça marche comment stp ? Tu pourrais m'en dire plus stp ?

  • CéroceCéroce Membre, Modérateur
    janvier 2016 modifié #11

    Dans le 1er cas ou il est dans if il est égal à  63, et dans le cas ou il est dans le else il est égal à  303 (mais s'affiche visiblement en 63).

    Il y a trois couches d'abstraction:
    - la UIView a une frame
    - la UIView est représentée par un CALayer qui a également une frame
    - la CALayer a également une presentationLayer qui a également une frame.

    Je n'en suis plus sûr, mais de mémoire, il me semble que quand on anime, seule la presentationLayer a sa frame qui change. C'est lorsque l'animation se termine que les 3 frames se réconcilient.
    Bref, je ne dis pas qu'il faut que tu descendes au niveau de Core Animation, mais j'essaye de t'expliquer pourquoi tu as ce résultat: à  mon avis fixer l'image appelle -setFrame: sur le bouton.

    Essaie plutôt quelque chose comme ça: ne pas fixer l'image dans le bloc d'animation:
    - (void) extandView {
    CGRect topViewFrame;
    CGRect expandButtonFrame;
    CGRect botViewFrame;

    if(self.isViewExpanded) {
    topViewFrame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height + heightTobeExpanded);
    expandButtonFrame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y + heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height);
    [expandButton setImage:[UIImage imageNamed:@arrow-top.png] forState:UIControlStateNormal];
    botViewFrame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y + heightTobeExpanded, view2.frame.size.width, view2.frame.size.height - heightTobeExpanded);
    } else {
    topViewFrame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height - heightTobeExpanded);
    expandButtonFrame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y - heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height );
    [expandButton setImage:[UIImage imageNamed:@arrow-bottom.png] forState:UIControlStateNormal];
    botViewFrame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y + heightTobeExpanded, view2.frame.size.width, view2.frame.size.height + heightTobeExpanded);
    }
    self.isViewExpanded = !self.isViewExpanded;

    [UIView animateWithDuration:1.0 delay:0.2 options:0 animations:^{
    self.view1.frame = topViewFrame;
    self.expandButton.frame = expandButtonFrame;
    self.view2.frame = botViewFrame;
    } completion:nil];
    }
    Pour finir: utilise l'autolayout. On peut animer les contraintes, et là , c'est vraiment ce qu'il faut faire. Changer les frames à  la main c'est plus facile mais ce sera plein de problèmes à  l'avenir quand tu devras gérer plusieurs tailles d'écrans.
  • Ben77650Ben77650 Membre
    janvier 2016 modifié #12

    Il y a trois couches d'abstraction:


    - la UIView a une frame
    - la UIView est représentée par un CALayer qui a également une frame
    - la CALayer a également une presentationLayer qui a également une frame.

    Je n'en suis plus sûr, mais de mémoire, il me semble que quand on anime, seule la presentationLayer a sa frame qui change. C'est lorsque l'animation se termine que les 3 frames se réconcilient.
    Bref, je ne dis pas qu'il faut que tu descendes au niveau de Core Animation, mais j'essaye de t'expliquer pourquoi tu as ce résultat: à  mon avis fixer l'image appelle -setFrame: sur le bouton.

     


     


    Ok je vois l'idée.


     



    Pour finir: utilise l'autolayout. On peut animer les contraintes, et là , c'est vraiment ce qu'il faut faire. Changer les frames à  la main c'est plus facile mais ce sera plein de problèmes à  l'avenir quand tu devras gérer plusieurs tailles d'écrans. 



     


    Oui j'ai déjà  eu à  le faire dans le vrai projet, et de toute je devrais le faire aussi dans le vrai projet, donc pas de souci à  ce niveau la, mais merci du conseil.


     


    Je teste et j'essaye de comprendre ton code autrement.


     


    Merci pour l'aide.




  • Essaie plutôt quelque chose comme ça: ne pas fixer l'image dans le bloc d'animation:



    - (void) extandView {
    CGRect topViewFrame;
    CGRect expandButtonFrame;
    CGRect botViewFrame;

    if(self.isViewExpanded) {
    topViewFrame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height + heightTobeExpanded);
    expandButtonFrame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y + heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height);
    [expandButton setImage:[UIImage imageNamed:@arrow-top.png] forState:UIControlStateNormal];
    botViewFrame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y + heightTobeExpanded, view2.frame.size.width, view2.frame.size.height - heightTobeExpanded);
    } else {
    topViewFrame = CGRectMake(view1.frame.origin.x, view1.frame.origin.y, view1.frame.size.width, view1.frame.size.height - heightTobeExpanded);
    expandButtonFrame = CGRectMake(expandButton.frame.origin.x, expandButton.frame.origin.y - heightTobeExpanded, expandButton.frame.size.width, expandButton.frame.size.height );
    [expandButton setImage:[UIImage imageNamed:@arrow-bottom.png] forState:UIControlStateNormal];
    botViewFrame = CGRectMake(view2.frame.origin.x, view2.frame.origin.y + heightTobeExpanded, view2.frame.size.width, view2.frame.size.height + heightTobeExpanded);
    }
    self.isViewExpanded = !self.isViewExpanded;

    [UIView animateWithDuration:1.0 delay:0.2 options:0 animations:^{
    self.view1.frame = topViewFrame;
    self.expandButton.frame = expandButtonFrame;
    self.view2.frame = botViewFrame;
    } completion:nil];
    }



     


    Il s'avère que le souci est bel et bien toujours présent même avec ce code, la position du bouton ne change pas, et la taille des vues non plus.


    D'autre part je trouve l'animation (celle de top vers bottom) relativement bizarre.


     


    Mais merci d'avoir essayé de m'aider :)

  • Personne a une idée du coup, pour faire ce que je souhaite s'il vous plait ?


  • Tu as essayé avec les contraintes telles qu'il semble que tu auras à  le faire dans le "vrai" projet ?


  • Pas encore pour le moment, j'essaye de le faire fonctionner sans contraintes, et une fois que ce sera fonctionnel, je le ferais avec contraintes




  • Pas encore pour le moment, j'essaye de le faire fonctionner sans contraintes, et une fois que ce sera fonctionnel, je le ferais avec contraintes




    Vire l'autolayout du Storyboard alors ?

  • Effectivement, ça marche merci.


     


    Maintenant je m'attaque à  la partie autolayout avec les contraintes :D


  • les constraintes c'est la solution...


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