如何停止不必要的UIButton动画标题变化?

在ios7中,我的UIButton标题在错误的时间动画进出——迟到。在iOS 6上不出现此问题。我用的是:

[self setTitle:text forState:UIControlStateNormal];

我更希望这能立即发生,而不是一个空白的框架。这种眨眼特别分散注意力,并将注意力从其他动画中转移开。

62763 次浏览

这适用于自定义按钮:

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

对于系统按钮,你需要在重新启用动画之前添加这个(谢谢@Klaas):

[_button layoutIfNeeded];

请注意:

当_button的"buttonType"为“UIButtonTypeSystem”时,下面的代码为无效的:

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

当_button的“buttonType”为“UIButtonTypeCustom”时,上述代码为有效的

我发现这个解决方法也适用于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)

结合以上的答案,可以得到以下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];
}

使用performWithoutAnimation:方法,然后强制布局立即发生,而不是稍后发生。

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

也许生成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;}];

所以我找到了可行的解决方案:

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

首先我们改变按钮的标题,然后调整这个标题的按钮大小

从iOS 7.1开始,唯一适合我的解决方案是用UIButtonTypeCustom类型初始化按钮。

你可以从标题标签层中删除动画:

    [[[theButton titleLabel] layer] removeAllAnimations];
当在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. titlabel .text的调用。 因此,为了仍然使用故事板,并像这样动态本地化组件,我确保将每个按钮的还原ID(在身份检查器中)设置为与标题相同,并将其用作键而不是标题;

for(UIView *v in view.subviews) {


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


}

不理想,但还行。

你可以简单地创建自定义按钮,它将停止动画而改变标题。

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

你也可以在Storyboard复选框中做: 在storyboard中选择按钮->选择属性检查器(左边第四个)->在“类型”下拉菜单中,选择“自定义”而不是可能被选中的“系统”

好运!

我得到了它的工作组合的答案:

[[[button titleLabel] layer] removeAllAnimations];


[UIView performWithoutAnimation:^{


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


}];

将按钮类型更改为自定义表单界面生成器。

enter image description here

这对我很管用。

你可以在动画块之外设置标题,只是要确保在performWithoutAnimation中调用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()
}

我已经做了一个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应该类似)

在Swift中,你可以使用:

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

将按钮类型设置为UIButtonTypeCustom,它将停止闪烁

通常简单地将按钮类型设置为自定义对我来说是有效的,但由于其他原因,我需要子类化UIButton并将按钮类型设置回默认(System),所以闪烁再次出现。

在更改标题之前设置UIView.setAnimationsEnabled(false),然后在更改标题之后再次设置为true,并不能避免我的闪烁,无论我是否调用self.layoutIfNeeded()

在iOS 9和10测试版中,我只按以下顺序做到了这一点:

1)为UIButton创建一个子类(不要忘记在Storyboard中为按钮设置自定义类)。

2)重写setTitle:forState:,如下所示:

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


UIView.performWithoutAnimation({


super.setTitle(title, forState: state)


self.layoutIfNeeded()
})
}

在Interface Builder中,您可以将按钮类型留给System,不需要将其更改为自定义类型以实现此方法。

我希望这能帮助其他人,我已经与烦人的闪烁按钮斗争了很长时间,我希望避免它对其他人;)

Xhacker Liu扩展转换为Swift 3:

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


setTitle(title, for: .normal)


layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}

设置UIButton类型为自定义。这应该会删除淡入和淡出动画。

一个方便的扩展动画按钮标题变化在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)
}
}
}

Swift 4版Xhacker刘回答

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


setTitle(title, for: .normal)


layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
}

斯威夫特5

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

具有system类型的UIButton在setTitle(_:for:)上有隐式动画。你可以用两种方法来解决这个问题:

  1. 从code或Interface Builder中设置按钮类型为custom:
let button = UIButton(type: .custom)

enter image description here

  1. 从代码中禁用动画:
UIView.performWithoutAnimation {
button.setTitle(title, for: .normal)
button.layoutIfNeeded()
}