Как остановить нежелательную анимацию UIButton при изменении названия?

В iOS 7 мои заголовки UIButton оживают и выходят в неподходящее время - поздно. Эта проблема не появляется на iOS 6. Я просто использую:

[self setTitle:text forState:UIControlStateNormal];

Я бы предпочел, чтобы это произошло мгновенно и без пустой рамки. Этот мигание особенно отвлекает внимание и отвлекает внимание от других анимаций.

Ответ 1

Это работает для пользовательских кнопок:

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

Для системных кнопок вам нужно добавить это перед повторной активацией анимации (спасибо @Klaas):

[_button layoutIfNeeded];

Ответ 2

Используйте метод performWithoutAnimation:, а затем принудительно создайте макет немедленно, а не позже.

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

Ответ 3

Измените тип кнопки на построитель интерфейса пользовательской формы.

enter image description here

Это сработало для меня.

Ответ 4

В Swift вы можете использовать:

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

Ответ 5

Обратите внимание:

когда "buttonType" кнопки _ "UIButtonTypeSystem" , ниже кода недействителен:

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

когда "buttonType" of_button "UIButtonTypeCustom" , код выше действителен.

Ответ 6

Начиная с iOS 7.1 единственным решением, которое сработало для меня, была инициализация кнопки с типом UIButtonTypeCustom.

Ответ 7

поэтому я нахожу отработанное решение:

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

вначале мы меняем название кнопки, затем изменяем размер для этого названия

Ответ 8

Задайте тип кнопки UIButtonTypeCustom, и она перестанет мигать

Ответ 9

Ive сделал расширение Swift для этого:

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

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Работает для меня на iOS 8 и 9, с UIButtonTypeSystem.

(Код для Swift 2, Swift 3 и Objective-C должен быть похож)

Ответ 10

Задайте тип UIButton как пользовательский. Это должно удалить выцветание в и из анимаций.

Ответ 11

Вы можете просто создать пользовательскую кнопку, и она остановит анимацию при изменении названия.

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

вы также можете сделать это в ракурсе: выберите кнопку в раскадровке → выберите инспектор атрибутов (четвертый слева) → в раскрывающемся меню "Тип", выберите "Пользовательский" вместо "Система", который, вероятно, был выбран.

Удачи!

Ответ 12

Обычно просто настройка типа кнопки для Custom работает для меня, но по другим причинам мне нужно было подклассифицировать UIButton и установить тип кнопки обратно по умолчанию (System), поэтому мигание снова появилось.

Настройка UIView.setAnimationsEnabled(false) перед изменением заголовка, а затем снова на true, после чего не избежать мигания для меня, независимо от того, вызвал ли я self.layoutIfNeeded() или нет.

Это, и только это в следующем точном порядке, сработало для меня с iOS 9 и 10 beta:

1) Создайте подкласс для UIButton (не забудьте также установить пользовательский класс для кнопки в Storyboard).

2) Переопределить setTitle:forState: следующим образом:

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

В интерфейсе Builder вы можете оставить тип кнопки в Системе, не нужно менять ее на пользовательский тип, чтобы этот подход работал.

Я надеюсь, что это поможет кому-то другому, я так долго боролся с раздражающими мигающими кнопками, которые я надеюсь избежать этого другим;)

Ответ 13

Вы можете удалить анимации из слоя надписи:

    [[[theButton titleLabel] layer] removeAllAnimations];

Ответ 14

Swift 4 версия ответа Xhacker Лю

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 

Ответ 15

Я обнаружил, что это обходное решение работает с UIButtonTypeSystem, но будет работать, только если кнопка включена по какой-либо причине.

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

Поэтому вам нужно будет добавить их, если вам нужно, чтобы кнопка была отключена при настройке ее названия.

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

(iOS 7, Xcode 5)

Ответ 16

Объединение больших ответов приводит к следующему обходному пути для UIButtonTypeSystem:

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

Ответ 17

У меня возникла уродливая проблема с анимацией при смене заголовков кнопок в контроллерах UITabBarController. Названия, которые первоначально были установлены в раскадровке, появились на короткое время, прежде чем исчезнуть в их новые значения.

Я хотел выполнить итерацию по всем подзонам и использовать названия кнопок в качестве ключей, чтобы получить их локализованные значения с помощью NSLocalizedString, например;

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

}

Я узнал, что инициирование анимации - это действительно вызов btn.titleLabel.text. Поэтому, чтобы все еще использовать раскадровки и иметь динамически локализованные компоненты, я должен установить каждую кнопку Restoration ID (в Identity Inspector) так же, как и название, и использовать это как ключ вместо названия;

for(UIView *v in view.subviews) {

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

}

Не идеально, но работает.

Ответ 18

Фактически вы можете установить заголовок вне блока анимации, просто позвоните layoutIfNeeded() внутри функции исполнения без разрешения:

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

Если у вас есть куча кнопок, рассмотрите только вызов layoutIfNeeded() в супер-представлении:

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

Ответ 19

Расширение Xhacker Liu, преобразованное в Swift 3:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Ответ 20

Swift 5

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

Ответ 21

Возможно, создание 2 анимаций и 2 кнопок - лучшее решение, чтобы избежать проблемы, возникающей при анимации и изменении текста кнопки?

Я создал вторую uibutton и сгенерировал 2 анимации, это решение работает без hickup.

    _button2.hidden = TRUE;
    _button1.hidden = FALSE;

    CGPoint startLocation = CGPointMake(_button1.center.x, button1.center.y - 70);
    CGPoint stopLocation  = CGPointMake(_button2.center.x, button2.center.y- 70);


    [UIView animateWithDuration:0.3 animations:^{ _button2.center = stopLocation;} completion:^(BOOL finished){_button2.center = stopLocation;}];
    [UIView animateWithDuration:0.3 animations:^{ _button1.center = startLocation;} completion:^(BOOL finished){_button1.center = startLocation;}];

Ответ 22

Я получил его для работы с комбинацией ответов:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

        [button setTitle:@"Title" forState:UIControlStateNormal];

    }];

Ответ 23

Удобное расширение для изменения заголовка анимированной кнопки в Swift, которое прекрасно сочетается с реализацией по умолчанию:

import UIKit

extension UIButton {
  /// By default iOS animated the title change, which is not desirable in reusable views
  func setTitle(_ title: String?, for controlState: UIControlState, animated: Bool = true) {
    if animated {
      setTitle(title, for: controlState)
    } else {
      UIView.setAnimationsEnabled(false)
      setTitle(title, for: controlState)
      layoutIfNeeded()
      UIView.setAnimationsEnabled(true)
    }
  }
}