В iOS 7 мои заголовки UIButton оживают и выходят в неподходящее время - поздно. Эта проблема не появляется на iOS 6. Я просто использую:
[self setTitle:text forState:UIControlStateNormal];
Я бы предпочел, чтобы это произошло мгновенно и без пустой рамки. Этот мигание особенно отвлекает внимание и отвлекает внимание от других анимаций.
Это работает для пользовательских кнопок:
[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
Для системных кнопок вам нужно добавить это перед повторной активацией анимации (спасибо @Klaas):
[_button layoutIfNeeded];
Используйте метод performWithoutAnimation:
, а затем принудительно создайте макет немедленно, а не позже.
[UIView performWithoutAnimation:^{
[self.myButton setTitle:text forState:UIControlStateNormal];
[self.myButton layoutIfNeeded];
}];
Обратите внимание:
когда "buttonType" кнопки _ "UIButtonTypeSystem" , ниже кода недействителен:
[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
когда "buttonType" of_button "UIButtonTypeCustom" , код выше действителен.
Начиная с iOS 7.1 единственным решением, которое сработало для меня, была инициализация кнопки с типом UIButtonTypeCustom
.
Измените тип кнопки на построитель интерфейса пользовательской формы.
Это сработало для меня.
В Swift вы можете использовать:
UIView.performWithoutAnimation {
self.someButtonButton.setTitle(newTitle, forState: .normal)
self.someButtonButton.layoutIfNeeded()
}
поэтому я нахожу отработанное решение:
_logoutButton.titleLabel.text = NSLocalizedString(@"Logout",);
[_logoutButton setTitle:_logoutButton.titleLabel.text forState:UIControlStateNormal];
вначале мы меняем название кнопки, затем изменяем размер для этого названия
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 должен быть похож)
Задайте тип кнопки UIButtonTypeCustom, и она перестанет мигать
Вы можете просто создать пользовательскую кнопку, и она остановит анимацию при изменении названия.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"the title" forState:UIControlStateNormal];
вы также можете сделать это в ракурсе: выберите кнопку в раскадровке → выберите инспектор атрибутов (четвертый слева) → в раскрывающемся меню "Тип", выберите "Пользовательский" вместо "Система", который, вероятно, был выбран.
Удачи!
Вы можете удалить анимации из слоя надписи:
[[[theButton titleLabel] layer] removeAllAnimations];
Расширение Xhacker Liu, преобразованное в Swift 3:
extension UIButton {
func setTitleWithoutAnimation(title: String?) {
UIView.setAnimationsEnabled(false)
setTitle(title, for: .normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}
Обычно просто настройка типа кнопки для 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 вы можете оставить тип кнопки в Системе, не нужно менять ее на пользовательский тип, чтобы этот подход работал.
Я надеюсь, что это поможет кому-то другому, я так долго боролся с раздражающими мигающими кнопками, которые я надеюсь избежать этого другим;)
layoutIfNeeded()
:]
Фактически вы можете установить заголовок вне блока анимации, просто позвоните 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()
}
У меня возникла уродливая проблема с анимацией при смене заголовков кнопок в контроллерах 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];
}
}
Не идеально, но работает.
Я обнаружил, что это обходное решение работает с 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)
Задайте тип UIButton как пользовательский. Это должно удалить выцветание в и из анимаций.
Я получил его для работы с комбинацией ответов:
[[[button titleLabel] layer] removeAllAnimations];
[UIView performWithoutAnimation:^{
[button setTitle:@"Title" forState:UIControlStateNormal];
}];
Возможно, создание 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;}];
Объединение больших ответов приводит к следующему обходному пути для 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];
}