web-dev-qa-db-fra.com

Comment arrêter une animation UIButton indésirable sur le changement de titre?

Sous iOS 7, mes titres UIButton s'animent au mauvais moment, tardivement. Ce problème n'apparaît pas sur iOS 6. J'utilise seulement:

[self setTitle:text forState:UIControlStateNormal];

Je préférerais que cela se produise instantanément et sans cadre vierge. Ce clignotement est particulièrement gênant et détourne l’attention des autres animations.

195
exsulto

Cela fonctionne pour les boutons personnalisés:

[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

Pour les boutons système, vous devez ajouter ceci avant de réactiver les animations (merci @Klaas):

[_button layoutIfNeeded];
157
Jacob K

Utilisez la méthode performWithoutAnimation: puis forcez la disposition à se produire immédiatement au lieu de plus tard.

[UIView performWithoutAnimation:^{
  [self.myButton setTitle:text forState:UIControlStateNormal];
  [self.myButton layoutIfNeeded];
}];
244
Snowman

Changez le type de bouton en constructeur de l'interface de formulaire personnalisée.

enter image description here

Cela a fonctionné pour moi.

72

Dans Swift, vous pouvez utiliser:

UIView.performWithoutAnimation {
    self.someButtonButton.setTitle(newTitle, forState: .normal)
    self.someButtonButton.layoutIfNeeded()
}
62
Paulw11

S'il vous plaît noter:

lorsque " buttonType " de _button est "UIButtonTypeSystem", le code ci-dessous est invalide

[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

lorsque " buttonType " de _button est "UIButtonTypeCustom", le code ci-dessus est valide.

59
shede333

À partir de iOS 7.1, la seule solution qui fonctionnait pour moi était l’initialisation du bouton de type UIButtonTypeCustom.

50
Norbert

donc je trouve la solution travaillée:

_logoutButton.titleLabel.text = NSLocalizedString(@"Logout",);
[_logoutButton setTitle:_logoutButton.titleLabel.text forState:UIControlStateNormal];

en premier nous changeons le titre du bouton, puis redimensionnons le bouton pour ce titre

18
dubenko

Définissez le type de bouton sur UIButtonTypeCustom et il ne clignotera plus.

13
arunjos007

J'ai fait une extension Swift pour le faire:

extension UIButton {
    func setTitleWithoutAnimation(title: String?) {
        UIView.setAnimationsEnabled(false)

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Fonctionne pour moi sur iOS 8 et 9, avec UIButtonTypeSystem.

(Le code est pour Swift 2, Swift 3 et Objective-C doivent être similaires)

12
Xhacker Liu

Définissez le type UIButton sur Personnalisé. Cela devrait supprimer les animations de fondu en entrée et en sortie.

8
Amit Tandel

Vous pouvez simplement créer un bouton personnalisé qui arrêtera de s'animer lors du changement de titre.

        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [btn setTitle:@"the title" forState:UIControlStateNormal];

vous pouvez également le faire dans la case à cocher Storyboard: sélectionnez le bouton dans le storyboard -> sélectionnez l'inspecteur d'attributs (quatrième à gauche) -> dans le menu déroulant "Type", sélectionnez "Personnalisé" au lieu de "Système" qui a probablement été sélectionné .

Bonne chance!

6
Mendy

Habituellement, le simple fait de définir le type de bouton sur Personnalisé fonctionne pour moi, mais pour d'autres raisons, j'ai dû sous-classer UIButton et redéfinir le type de bouton sur la valeur par défaut (Système) afin que le clignotement réapparaisse.

Régler UIView.setAnimationsEnabled(false) avant de changer le titre, puis de revenir à true après, cela ne m'a pas évité de clignoter, peu importe si j'ai appelé self.layoutIfNeeded() ou non.

Ceci, et seulement cela dans l'ordre exact suivant, a fonctionné pour moi avec iOS 9 et 10 bêta:

1) Créez une sous-classe pour UIButton (n'oubliez pas de définir également la classe personnalisée pour le bouton dans le Storyboard).

2) Remplacer setTitle:forState: comme suit:

override func setTitle(title: String?, forState state: UIControlState) {

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

Dans Interface Builder, vous pouvez laisser le type de bouton à Système, il n'est pas nécessaire de le changer en Type personnalisé pour que cette approche fonctionne.

J'espère que cela aide quelqu'un d'autre, je lutte depuis si longtemps avec les boutons clignotants agaçants que j'espère éviter aux autres;)

6
cdf1982

version Swift 4 de Xhacker Liu answer

import Foundation
import UIKit
extension UIButton {
    func setTitleWithOutAnimation(title: String?) {
        UIView.setAnimationsEnabled(false)

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 
3
faraz khonsari

Vous pouvez supprimer les animations du calque de l'étiquette de titre:

    [[[theButton titleLabel] layer] removeAllAnimations];
3
Jacksonh

Swift 5

myButton.titleLabel?.text = "title"
myButton.setTitle("title", for: .normal)
1
Carter Randall

Vous pouvez réellement définir le titre en dehors d'un bloc d'animation, assurez-vous simplement d'appeler layoutIfNeeded() à l'intérieur d'un performWithoutAnimation:

button1.setTitle("abc", forState: .Normal)
button2.setTitle("abc", forState: .Normal)
button3.setTitle("abc", forState: .Normal)
UIView.performWithoutAnimation {
    self.button1.layoutIfNeeded()
    self.button2.layoutIfNeeded()
    self.button3.layoutIfNeeded()
}

Si vous avez plusieurs boutons, appelez simplement layoutIfNeeded() sur la vue super:

button1.setTitle("abc", forState: .Normal)
button2.setTitle("abc", forState: .Normal)
button3.setTitle("abc", forState: .Normal)
UIView.performWithoutAnimation {
    self.view.layoutIfNeeded()
}
0
Senseful

J'ai trouvé que cette solution de contournement fonctionne avec IButtonTypeSystem également mais ne fonctionnera que si le bouton est activé pour une raison quelconque.

[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

Vous devrez donc les ajouter si vous souhaitez que le bouton soit désactivé lors de la définition de son titre.

[UIView setAnimationsEnabled:NO];
_button.enabled = YES;
[_button setTitle:@"title" forState:UIControlStateNormal];
_button.enabled = NO;
[UIView setAnimationsEnabled:YES];

(iOS 7, Xcode 5)

0
sCha

J'ai eu le problème d'animation moche lors de la modification des titres de bouton dans les contrôleurs de vue dans un UITabBarController. Les titres qui étaient à l'origine dans le storyboard sont apparus pendant un court moment avant de se fondre dans leurs nouvelles valeurs.

Je voulais parcourir toutes les vues secondaires et utiliser les titres de bouton comme clés pour obtenir leurs valeurs localisées avec NSLocalizedString, telles que;

for(UIView *v in view.subviews) {

    if ([v isKindOfClass:[UIButton class]]) {
        UIButton *btn = (UIButton*)v;
        NSString *newTitle = NSLocalizedString(btn.titleLabel.text, nil);
        [btn setTitle:newTitle];
    }

}

J'ai découvert que ce qui déclenche l'animation est vraiment l'appel à btn.titleLabel.text. Donc, pour continuer à utiliser les story-boards et à localiser dynamiquement les composants de cette manière, je m'assure de définir l'identifiant de restauration de chaque bouton (dans l'inspecteur d'identité) sur le même titre que le titre et de l'utiliser comme clé au lieu du titre;

for(UIView *v in view.subviews) {

    if ([v isKindOfClass:[UIButton class]]) {
        UIButton *btn = (UIButton*)v;
        NSString *newTitle = NSLocalizedString(btn.restorationIdentifier, nil);
        [btn setTitle:newTitle];
    }

}

Pas idéal, mais ça marche ..

0
Michael

L'extension Xhacker Liu convertie en Swift 3:

extension UIButton {
    func setTitleWithoutAnimation(title: String?) {
        UIView.setAnimationsEnabled(false)

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}
0
Paweł

En combinant les réponses ci-dessus, vous obtenez la solution suivante pour IButtonTypeSystem:

if (_button.enabled)
{
    [UIView setAnimationsEnabled:NO];
    [_button setTitle:@"title" forState:UIControlStateNormal];
    [UIView setAnimationsEnabled:YES];
}
else // disabled
{
    [UIView setAnimationsEnabled:NO];
    _button.enabled = YES;
    [_button setTitle:@"title" forState:UIControlStateNormal];
    _button.enabled = NO;
    [UIView setAnimationsEnabled:YES];
}
0
AppsolutEinfach