Come evitare che il pulsante UIB lampeggi durante l'aggiornamento del titolo


85

Quando chiamo setTitle su un UIButton, il pulsante lampeggia in iOS 7. Ho provato a impostare myButton.highlighted = NO, ma questo non ha impedito al pulsante di lampeggiare.

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

myButton.highlighted = NO;

Ecco come ho impostato il timer che ha aggiornato i titoli:

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

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

Ecco il metodo che aggiorna effettivamente i titoli:

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

Non dovrebbe lampeggiare. Stai provando a farlo su un thread in background?
BergQuester

Sì, viene impostato in un timer per aggiornare il titolo del pulsante ogni secondo (che penso crei il proprio thread)
FierceMonkey

I timer vengono eseguiti su un thread separato solo se impostati per farlo. Potremmo vedere il metodo in cui il titolo viene aggiornato e come si imposta il timer?
BergQuester

Ho aggiunto il codice richiesto alla domanda principale
FierceMonkey

Risposte:


208

Imposta il tipo di pulsante su UIButtonTypeCustom e smetterà di lampeggiare


16
Questa dovrebbe essere davvero la risposta preferita. La soluzione più semplice. E funziona.
Johan Karlsson

4
Concordato. Ho provato molte altre soluzioni e questa è la cosa che ha funzionato, tutto da solo.
BBQ Steve

2
Questa dovrebbe essere la risposta accettata. Finora la soluzione più semplice.
Machado,

1
Funziona come un fascino! Grazie

2
Penso che questa sia davvero una buona soluzione senza scrivere alcun codice per questo.
Chauyan

58

Un approccio migliore di [UIView setAnimationsEnabled:NO] che potrebbe influire su altre animazioni è disabilitare solo l'animazione del titolo specifica.

Obiettivo-C:

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

Swift:

UIView.performWithoutAnimation { 
    myButton.setTitle(text, for: .normal)
    myButton.layoutIfNeeded()
}

Proprio ora ho provato la soluzione Swift sull'ultimo iOS: funziona alla grande.
Ronen Rabinovici

1
Salvatore del giorno. Saluti!
pkc456

Ho appena provato questo in Swift 3 e funziona senza l'uso di layoutIfNeeded ()
user1898712

3
Questa dovrebbe essere la risposta accettata senza dubbio!
Julius

1
Questo è il modo migliore per farlo. Bella risposta!
dicembre

29

* Nota *

quando " buttonType " di _button è "UIButtonTypeSystem" , il codice sottostante non è valido

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

quando " buttonType " di _button è "UIButtonTypeCustom" , il codice sopra è valido .


19

Vedi le risposte da Come fermare l'animazione UIButton indesiderata al cambio di titolo? :

[UIView setAnimationsEnabled:NO];
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

7
@FierceMonkey provare ad aggiungere una chiamata a layoutIfNeeded: [elapsed layoutIfNeeded];. Questo ha rimosso il battito di ciglia nel mio caso.
Klaas

1
layoutIfNeeded l'ha fatto per me.
Kaolin Fire

Sembra essere una soluzione alternativa piuttosto sporca, tuttavia layoutIfNeededsembrerebbe funzionare
Przemysław Wrzesiński

7

Puoi semplicemente creare un'altra funzione per UIButton per un facile utilizzo futuro.

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

Questo è tutto!

E imposta il titolo come faresti prima, ma sostituiscilo setTitleconsetTitleWithoutAnimation


6

Il comportamento predefinito "setTitle" è decisamente odioso!

La mia soluzione è:

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

Inoltre, nello storyboard, sotto la proprietà del pulsante deseleziono:

  • Inverte su evidenziazione
  • Evidenziato Regola immagine

E controlla:

  • Disattivato Regola immagine

Testato e funzionante anche su iOS 8 .

Aggiornamento - Swift

Ti suggerisco di creare il tuo pulsante personalizzato e di sovrascrivere il metodo setTitle .

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

}

Ho provato questo approccio (sottoclasse, sovrascrittura di setTitle: forState: e disabilitazione-abilitazione UIView.setAnimationsEnabled). Non funziona per me in iOS 9 e 10 beta. Funziona se disabilito solo le animazioni, ma poi vengono perse per ogni UIView ...
cdf1982

2

Prova questo, funziona nelle versioni più recenti di IOS:

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

}

0

Sono nuovo nella codifica e nello Stackoverflow, quindi non ho abbastanza reputazione per commentare direttamente per espandere la https://stackoverflow.com/users/4673064/daniel-tseng ottima risposta. Quindi devo scrivere la mia nuova risposta, ed è questa:

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

Funziona alla grande, TRANNE:

Se tutte le mie chiamate successive nel codice a "setTitleWithoutAnimation" non specificano un mittente, ricevo questi strani messaggi relativi a CoreMedia o CoreData, ad esempio, "Impossibile ereditare le autorizzazioni CoreMedia da 2526: (null)"

Questo è probabilmente abbastanza semplice per la codifica e iOS, ma per me come nuovo programmatore, mi ha mandato su una pista da coniglio per un po ', come in: Oggi Estensione Impossibile ereditare le autorizzazioni CoreMedia da , da cui le persone avevano risposte interessanti ma NON raggiungere la radice del mio problema.

Così ho finalmente scoperto che dovevo passare attraverso e dare i miei parametri di funzioni senza parametri, cioè, dovevo specificare un mittente. Quel mittente potrebbe essere UIButton, Any o AnyObject. Tutti hanno funzionato, ma alla fine sembra esserci un conflitto tra l'aggiunta di un'estensione di pulsante con "self" e il non dire specificamente in seguito che un pulsante lo sta utilizzando.

Di nuovo, probabilmente di base, ma nuovo per me, quindi ho pensato che valesse la pena condividerlo.


0

Un altro trucco

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

Funziona solo se conosci il valore del titolo senza effettuare chiamate API. Il titolo del pulsante verrà impostato prima che la vista venga caricata, quindi non vedrai l'animazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.