首页 文章

如何在 Headers 更改时阻止不需要的UIButton动画?

提问于
浏览
176

在iOS 7中,我的UIButton游戏在错误的时间进行动画制作 - 迟到 . 这个问题不会出现在iOS 6上 . 我只是使用:

[self setTitle:text forState:UIControlStateNormal];

我希望这种情况立即发生,没有空白框架 . 这种眨眼特别令人分心,并引起人们对其他动画的注意 .

22 回答

  • 1

    将UIButton类型设置为Custom . 这应该删除淡入淡出动画 .

  • 18

    Swift中动画按钮 Headers 更改的便捷扩展,可与默认实现很好地配合使用:

    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)
        }
      }
    }
    
  • 44

    通常只是将按钮类型设置为Custom适用于我,但由于其他原因,我需要子类化UIButton并将按钮类型设置回默认值(系统),因此闪烁再次出现 .

    在更改 Headers 之前设置 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()
        })
    }
    

    在Interface Builder中,您可以将按钮类型保留为System,无需将其更改为Custom Type即可使此方法生效 .

    我希望这可以帮助别人,我已经用烦人的闪烁按钮挣扎了很长时间,我希望避免它给别人;)

  • 220

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

  • 0

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

    [[[theButton titleLabel] layer] removeAllAnimations];
    
  • 1

    我发现这个解决方法也适用于 UIButtonTypeSystem 但只有在按钮是 enabled 时才会起作用 .

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

    因此,如果您在设置 Headers 时需要禁用该按钮,则必须添加这些 .

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

    (iOS 7,Xcode 5)

  • 0

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

    我创建了第二个uibutton并生成了2个动画,这个解决方案没有hickups .

    _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;}];
    
  • 52

    Xhacker Liu扩展转换为Swift 3:

    extension UIButton {
        func setTitleWithoutAnimation(title: String?) {
            UIView.setAnimationsEnabled(false)
    
            setTitle(title, for: .normal)
    
            layoutIfNeeded()
            UIView.setAnimationsEnabled(true)
        }
    }
    
  • 1

    所以我找到了解决方案:

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

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

  • 0

    Swift 4 version of Xhacker Liu answer

    import Foundation
    import UIKit
    extension UIButton {
        func setTitleWithOutAnimation(title: String?) {
            UIView.setAnimationsEnabled(false)
    
            setTitle(title, for: .normal)
    
            layoutIfNeeded()
            UIView.setAnimationsEnabled(true)
        }
    }
    
  • 1

    您实际上可以在动画块之外设置 Headers ,只需确保在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()
    }
    
  • 6

    使用 performWithoutAnimation: 方法,然后立即强制布局,而不是以后 .

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

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

  • 11

    这适用于自定义按钮:

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

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

    [_button layoutIfNeeded];
    
  • 3

    您只需创建自定义按钮,它就会在更改 Headers 时停止动画 .

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

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

    祝好运!

  • 53

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

  • 144

    在Swift中你可以使用:

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

    Please note :

    当_button的“buttonType”是 "UIButtonTypeSystem" 时,下面的代码是 invalid

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

    当_button的“buttonType”为 "UIButtonTypeCustom" 时,上面的代码为 valid .

  • 4

    结合上面的好答案导致 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];
    }
    
  • 1

    在UITabBarController中的视图控制器中更改按钮 Headers 时,我遇到了丑陋的动画问题 . 最初在故事板中设置的 Headers 在淡入新值之前出现了一段时间 .

    我想迭代所有子视图并使用按钮 Headers 作为键来获取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中)设置为与 Headers 相同,并将其用作键而不是 Headers ;

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

    不理想,但工作..

  • 57

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

    enter image description here

    这对我有用 .

  • 0

    我得到它与答案组合工作:

    [[[button titleLabel] layer] removeAllAnimations];
    
        [UIView performWithoutAnimation:^{
    
            [button setTitle:@"Title" forState:UIControlStateNormal];
    
        }];
    

相关问题