236

In iOS 7 my UIButton titles are animating in and out at the wrong time - late. This problem does not appear on iOS 6. I'm just using:

[self setTitle:text forState:UIControlStateNormal];

I would prefer this happens instantly and without a blank frame. This blink is especially distracting and draws attention away from other animations.

4

24 回答 24

285

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

[UIView performWithoutAnimation:^{
  [self.myButton setTitle:text forState:UIControlStateNormal];
  [self.myButton layoutIfNeeded];
}];
于 2014-02-28T17:19:30.433 回答
169

这适用于自定义按钮:

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

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

[_button layoutIfNeeded];
于 2013-10-10T18:42:05.970 回答
101

在 Swift 中,您可以使用:

UIView.performWithoutAnimation {
    self.someButtonButton.setTitle(newTitle, forState: .normal)
    self.someButtonButton.layoutIfNeeded()
}
于 2015-12-09T00:43:20.997 回答
95

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

在此处输入图像描述

这对我有用。

于 2015-04-08T08:21:07.833 回答
61

请注意 :

当_button的“ buttonType ”为“UIButtonTypeSystem”时,下面的代码无效:</p>

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

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

于 2013-12-21T11:24:52.973 回答
55

从 iOS 7.1 开始,唯一对我有用的解决方案是使用 type 初始化按钮UIButtonTypeCustom

于 2014-04-22T20:52:37.087 回答
20

斯威夫特 5

myButton.titleLabel?.text = "title"
myButton.setTitle("title", for: .normal)
于 2019-07-05T21:15:51.537 回答
18

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

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

首先我们更改按钮的标题,然后调整此标题的按钮大小

于 2014-04-22T07:15:20.407 回答
14

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

于 2016-02-10T09:29:32.510 回答
14

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

于 2015-07-30T22:22:46.800 回答
14

system具有类型的UIButton在setTitle(_:for:). 您可以通过两种不同的方式修复它:

  1. custom通过代码或 Interface Builder将按钮类型设置为:
let button = UIButton(type: .custom)

在此处输入图像描述

  1. 从代码中禁用动画:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}
于 2020-05-22T10:03:40.363 回答
12

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

于 2017-12-15T09:07:50.440 回答
9

通常只需将按钮类型设置为自定义对我有用,但由于其他原因,我需要继承 UIButton 并将按钮类型设置回默认值(系统),因此闪烁再次出现。

在更改标题之前设置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,无需将其更改为 Custom Type 即可使用此方法。

我希望这对其他人有所帮助,我已经为烦人的闪烁按钮苦苦挣扎了很长时间,我希望避免对其他人造成影响;)

于 2016-08-09T10:00:38.560 回答
6

您可以简单地创建自定义按钮,它会在更改标题时停止动画。

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

您也可以在情节提要复选框中执行此操作:选择情节提要中的按钮-> 选择属性检查器(左侧第四个)-> 在“类型”下拉菜单中,选择“自定义”而不是可能已选择的“系统” .

祝你好运!

于 2014-06-16T11:06:00.303 回答
4

Swift 4 版 Xhacker 刘回答

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 
于 2018-10-10T17:32:14.680 回答
3

您可以从标题标签的图层中删除动画:

    [[[theButton titleLabel] layer] removeAllAnimations];
于 2014-04-23T17:47:56.020 回答
1

您实际上可以在动画块之外设置标题,只需确保layoutIfNeeded()在 performWithoutAnimation 内部调用:

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()
}
于 2015-07-29T19:19:44.540 回答
0

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

于 2014-02-11T12:59:06.527 回答
0

在 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 的调用。因此,为了仍然使用情节提要并让组件像这样动态本地化,我确保将每个按钮的恢复 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];
    }

}

不理想,但有效..

于 2014-05-24T21:35:39.967 回答
0

结合上述出色的答案,可以为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];
}
于 2014-02-18T14:36:04.007 回答
0

Xhacker Liu 扩展转换为 Swift 3:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}
于 2016-11-03T12:42:23.697 回答
0

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)
    }
  }
}
于 2018-07-31T14:46:08.260 回答
-1

我得到了它与答案的组合:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];
于 2015-02-17T12:16:37.467 回答
-2

也许生成 2 个动画和 2 个按钮是一个更好的解决方案,以避免出现动画和更改按钮文本的问题?

我创建了第二个 uibutton 并生成了 2 个动画,这个解决方案没有任何问题。

    _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;}];
于 2014-03-13T20:29:12.340 回答