Як запобігти блиманню кнопки UIB під час оновлення заголовка


85

Коли я викликаю setTitle на UIButton, кнопка блимає в iOS 7. Я спробував встановити myButton.highlighti = НІ, але це не завадило кнопці блимати.

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

myButton.highlighted = NO;

Ось як я налаштував таймер, який оновлював заголовки:

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

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

Ось метод, який фактично оновлює заголовки:

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

Це не повинно блимати. Ви намагаєтесь зробити це у фоновому режимі?
BergQuester

Так, це встановлюється в таймері, щоб щосекунди оновлювати заголовок кнопки (що, на мою думку, створити власний потік)
FierceMonkey

Таймери працюють лише в окремому потоці, якщо ви налаштували їх на це. Чи можемо ми побачити метод, де заголовок оновлюється і як ви налаштовуєте таймер?
BergQuester

Я додав запитуваний код до головного питання
FierceMonkey

Відповіді:


205

Встановіть для типу кнопки UIButtonTypeCustom, і він перестане блимати


16
Це справді має бути найкращою відповіддю. Найпростіше рішення. І це працює.
Йохан Карлссон,

4
Домовились. Я спробував багато інших рішень, і це те, що зробило це, само собою.
BBQ Steve

2
Це має бути прийнятою відповіддю. На сьогоднішній день найпростіше рішення.
Machado

1
Працює як шарм! Дякую

2
Я вважаю, що це дійсно хороше рішення, не написавши для цього жодного коду.
Чауян,

55

Кращий підхід, ніж той, [UIView setAnimationsEnabled:NO]що може вплинути на інші анімації, це лише вимкнення певної анімації заголовка.

Завдання-C:

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

Стрімкий:

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

Щойно спробував рішення Swift на останній iOS - чудово працює.
Ronen Rabinovici

1
День рятівника. На здоров’я!
pkc456

Щойно спробував це в Swift 3, і воно працює без використання layoutIfNeeded ()
user1898712

3
Це повинна бути прийнята відповідь без сумніву!
Юлій

1
Це найкращий спосіб зробити це. Чудова відповідь!
виїзд

29

* Зверніть увагу *

коли " buttonType " _button має значення "UIButtonTypeSystem" , код нижче недійсний :

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

коли « buttonType » з _button є «UIButtonTypeCustom» , наведений вище код є дійсним .


19

Дивіться відповіді з розділу Як зупинити небажану анімацію UIButton при зміні заголовка? :

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

7
@FierceMonkey спробуйте додати виклик layoutIfNeeded: [elapsed layoutIfNeeded];. Це видалило моргання в моєму випадку.
Клаас,

1
layoutIfNeeded зробив це за мене.
Kaolin Fire

Це, здається, досить брудне рішення, однак layoutIfNeeded, здається, працює
Перемислав Вжесінський

7

Ви можете просто зробити іншу функцію для UIButton для зручного використання в майбутньому.

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

Це все!

І просто встановіть заголовок, як і раніше, але замініть setTitleнаsetTitleWithoutAnimation


6

Поведінка "setTitle" за замовчуванням однозначно ненависна!

Моє рішення:

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

Крім того, в раскадровці, у властивості кнопки я знімаю прапорець:

  • Зворотно на виділеному
  • Виділене налаштування зображення

І перевірте:

  • Вимкнено Налаштування зображення

Протестовано і працює на iOS 8 теж.

Оновлення - швидкий

Я пропоную вам створити власну кнопку та замінити метод 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)
    }

}

Я спробував цей підхід (підклас, перевизначення setTitle: forState: та відключення-включення UIView.setAnimationsEnabled). Не працює у мене в iOS 9 і 10 beta. Це працює, якщо я лише
вимикаю

2

Спробуйте це, це працює в нових версіях IOS:

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

}

0

Я новачок у кодуванні та Stackoverflow, тому не маю достатньої репутації, щоб коментувати безпосередньо, щоб розширити https://stackoverflow.com/users/4673064/daniel-tseng чудова відповідь. Тож я повинен написати власну нову відповідь, і вона така:

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

Чудово працює, КРИМ:

Якщо всі мої виклики пізніше в коді до "setTitleWithoutAnimation" не вказують відправника, то я отримую ці дивні повідомлення, пов'язані з CoreMedia або CoreData, наприклад, "Не вдалося успадкувати дозволи CoreMedia від 2526: (нуль)"

Це, мабуть, досить базово для кодування та iOS, але для мене, як для нового кодера, це ненадовго відправило мене на кролицький шлях, як у: Сьогодні розширення не змогло успадкувати дозволи CoreMedia , де люди мали цікаві відповіді, але це НЕ досягти кореня моєї проблеми.

Тож я нарешті виявив, що мені довелося пройти і ввести параметри моїх функцій без параметрів, тобто мені потрібно було вказати відправника. Таким відправником може бути UIButton, Any або AnyObject. Усі вони працювали, але, зрештою, виникає конфлікт між додаванням розширення кнопки із "self" та тим, що не сказано пізніше про те, що кнопка використовує його.

Знову ж таки, мабуть, базове, але нове для мене, тож я зрозумів, що варто було б цим поділитися.


0

Ще одна хитрість

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

Це працює, лише якщо ви знаєте значення заголовка, не здійснюючи жодних викликів API. Заголовок кнопки буде встановлений перед завантаженням подання, тому ви не побачите анімацію

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.