So verhindern Sie, dass UIButton beim Aktualisieren des Titels blinkt

83

Wenn ich setTitle auf einem UIButton aufrufe, blinkt die Schaltfläche in iOS 7. Ich habe versucht, myButton.highlighted = NO zu setzen, aber das hat das Blinken der Schaltfläche nicht gestoppt.

[myButton setTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"elapsedLabelKey"] forState:UIControlStateNormal];

myButton.highlighted = NO;

So habe ich den Timer eingerichtet, der die Titel aktualisiert hat:

- (void)actionTimer {
    if (myTimer == nil) {

        myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
                        target: self
                        selector: @selector(showActivity)
                        userInfo: nil
                        repeats: YES];
    }
}

Hier ist die Methode, mit der die Titel tatsächlich aktualisiert werden:

- (void)showActivity {

    NSString *sym = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];

    if (pauseInterval == nil) {

        // Update clock
        seconds = [[NSDate date] timeIntervalSinceDate:startInterval] - breakTime;

        // Update total earned
        secRate = rate.value / 60 / 60;
        total = secRate * seconds;
        [totalLabel setTitle:[NSString stringWithFormat:@"%@%.4f",sym,total] forState:UIControlStateNormal];

        days = seconds / (60 * 60 * 24);
        seconds -= days * (60 * 60 * 24);
        int hours = seconds / (60 * 60);
        fhours = (float)seconds / (60.0 * 60.0);
        seconds -= hours * (60 * 60);
        int minutes = seconds / 60;
        seconds -= minutes * 60;

        // Update the timer clock
        [elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
    }
}
FierceMonkey
quelle
Es sollte nicht blinken. Versuchen Sie dies in einem Hintergrund-Thread zu tun?
BergQuester
Ja, es wird in einem Timer eingestellt, um den Schaltflächentitel jede Sekunde zu aktualisieren (was meiner Meinung nach einen eigenen Thread erstellt)
FierceMonkey
Timer werden nur in einem separaten Thread ausgeführt, wenn Sie sie dafür eingerichtet haben. Könnten wir sehen, wie der Titel aktualisiert wird und wie Sie den Timer einrichten?
BergQuester
Ich habe den angeforderten Code zur Hauptfrage hinzugefügt
FierceMonkey

Antworten:

203

Setzen Sie den Schaltflächentyp auf UIButtonTypeCustom und er hört auf zu blinken

Quanlong
quelle
16
Dies sollte wirklich die bevorzugte Antwort sein. Die einfachste Lösung. Und es funktioniert.
Johan Karlsson
4
Einverstanden. Ich habe viele andere Lösungen ausprobiert und das ist das, was es getan hat, ganz von alleine.
BBQ Steve
2
Dies sollte die akzeptierte Antwort sein. Bisher einfachste Lösung.
Machado
1
Klappt wunderbar! Danke
2
Ich denke, das ist eine wirklich gute Lösung, ohne dafür Code zu schreiben.
Chauyan
51

Ein besserer Ansatz, [UIView setAnimationsEnabled:NO]der sich auf andere Animationen auswirken kann, besteht darin, nur die spezifische Titelanimation zu deaktivieren.

Ziel c:

[UIView performWithoutAnimation:^{
  [myButton setTitle:text forState:UIControlStateNormal];
  [myButton layoutIfNeeded];
}];

Schnell:

UIView.performWithoutAnimation { 
    myButton.setTitle(text, for: .normal)
    myButton.layoutIfNeeded()
}
Cœur
quelle
Gerade die Swift-Lösung auf dem neuesten iOS ausprobiert - funktioniert super.
Ronen Rabinovici
1
Tagesretter. Prost!
pkc456
Ich habe es gerade in Swift 3 versucht und es funktioniert ohne die Verwendung von layoutIfNeeded ()
user1898712
3
Dies sollte ohne Zweifel die akzeptierte Antwort sein!
Julius
1
Dies ist der beste Weg, dies zu tun. Gute Antwort!
aecend
28

* Bitte beachten Sie *

Wenn " buttonType " von _button "UIButtonTypeSystem" ist , ist der folgende Code ungültig :

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

Wenn " buttonType " von _button "UIButtonTypeCustom" ist , ist der obige Code gültig .

shede333
quelle
19

Siehe die Antworten unter Wie kann ich unerwünschte UIButton-Animationen bei Titeländerungen stoppen? ::

[UIView setAnimationsEnabled:NO];
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
Marius
quelle
7
@FierceMonkey versuchen, einen Aufruf hinzuzufügen an layoutIfNeeded: [elapsed layoutIfNeeded];. Dies beseitigte das Blinken in meinem Fall.
Klaas
1
layoutIfNeeded hat es für mich getan.
Kaolin Feuer
Es scheint eine ziemlich schmutzige Problemumgehung zu sein, layoutIfNeededscheint jedoch zu funktionieren
Przemysław Wrzesiński
7

Sie können einfach eine andere Funktion für UIButton erstellen, um die zukünftige Verwendung zu vereinfachen.

extension UIButton {
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
        UIView.performWithoutAnimation {
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        }
    }
}

Das ist es!

Und setzen nur den Titel , wie Sie , bevor würde aber ersetzen setTitlemitsetTitleWithoutAnimation

Daniel Tseng
quelle
6

Das Standardverhalten von "setTitle" ist definitiv hasserfüllt!

Meine Lösung ist:

[UIView setAnimationsEnabled:NO];
[_button layoutIfNeeded]; 
[_button setTitle:[NSString stringWithFormat:@"what" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

Außerdem deaktiviere ich im Storyboard unter der Eigenschaft der Schaltfläche Folgendes:

  • Storniert bei Markierung
  • Markiert Bild anpassen

Und prüfe:

  • Deaktiviert Bild anpassen

Getestet und funktioniert auch unter iOS 8 .

Update - Schnell

Ich empfehle Ihnen, Ihre benutzerdefinierte Schaltfläche zu erstellen und die setTitle- Methode zu überschreiben .

class UnflashingButton: UIButton {
   
    override func setTitle(title: String?, forState state: UIControlState) {
        UIView.setAnimationsEnabled(false)
        self.layoutIfNeeded()
        super.setTitle(title, forState: state)
        UIView.setAnimationsEnabled(true)
    }

}
Luca Davanzo
quelle
Ich habe diesen Ansatz ausprobiert (Unterklassen, Überschreiben von setTitle: forState: und Deaktivieren und Aktivieren von UIView.setAnimationsEnabled). Funktioniert nicht für mich in iOS 9 und 10 Beta. Es funktioniert, wenn ich nur die Animationen deaktiviere, aber dann sind sie für jede UIView verloren ...
cdf1982
2

Versuchen Sie dies, dies funktioniert in neueren Versionen von IOS:

class CustomButtonWithNoEffect : UIButton {
    override func setTitle(_ title: String?, for state: UIControlState) {
        UIView.performWithoutAnimation {
            super.setTitle(title, for: state)
            super.layoutIfNeeded()
        }
    }

}
Kárpáti András
quelle
0

Ich bin neu in Codierung und Stackoverflow, habe also nicht genug Ruf, um direkt Kommentare abzugeben, um https://stackoverflow.com/users/4673064/daniel-tseng zu erweitern. Hervorragende Antwort. Also muss ich meine eigene neue Antwort schreiben und es ist diese:

extension UIButton {
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
        UIView.performWithoutAnimation {
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        }
    }
}

Funktioniert super, AUSSER:

Wenn alle meine Aufrufe später im Code zu "setTitleWithoutAnimation" keinen Absender angeben, erhalte ich diese seltsamen Nachrichten in Bezug auf CoreMedia oder CoreData, z. B. "Fehler beim Erben der CoreMedia-Berechtigungen von 2526: (null)".

Dies ist wahrscheinlich ziemlich einfach für Codierung und iOS, aber für mich als neuen Codierer hat es mich für eine Weile auf eine Kaninchenspur geschickt, wie in: Heute-Erweiterung konnte CoreMedia-Berechtigungen nicht erben , von denen die Leute interessante Antworten hatten, aber das tat es NICHT Erreiche die Wurzel meines Problems.

So stellte ich schließlich fest, dass ich meine parameterlosen Funktionsparameter durchgehen und angeben musste, dh ich musste einen Absender angeben. Dieser Absender kann UIButton, Any oder AnyObject sein. Alle diese Funktionen haben funktioniert, aber letztendlich scheint es einen Konflikt zwischen dem Hinzufügen einer Schaltflächenerweiterung mit "self" und dem späteren Hinweis zu geben, dass eine Schaltfläche diese verwendet.

Wieder wahrscheinlich einfach, aber neu für mich, also dachte ich, es würde sich lohnen, es zu teilen.

Ian Hanson
quelle
0

Ein weiterer Trick

@IBOutlet private weak var button: UIButton! {
    didSet {
        button.setTitle(title, for: .normal)
    }
}

Dies funktioniert nur, wenn Sie den Wert des Titels kennen, ohne API-Aufrufe durchzuführen. Der Titel der Schaltfläche wird vor dem Laden der Ansicht festgelegt, sodass die Animation nicht angezeigt wird

TunaTheDog
quelle