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];
    }
}

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


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()
}

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 .


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];

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


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)
    }

}

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()
        }
    }

}

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.


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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.