更新标题时如何防止UIButton闪烁

Posted

技术标签:

【中文标题】更新标题时如何防止UIButton闪烁【英文标题】:How to prevent UIButton from flashing when updating the title 【发布时间】:2013-10-15 00:42:05 【问题描述】:

当我在 UIButton 上调用 setTitle 时,按钮在 ios 7 中闪烁。我尝试设置 myButton.highlighted = NO,但这并没有阻止按钮闪烁。

[myButton setTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"elapsedLabelKey"] forState:UIControlStateNormal];

myButton.highlighted = NO;

这是我设置更新标题的计时器的方法:

- (void)actionTimer 
    if (myTimer == nil) 

        myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
                        target: self
                        selector: @selector(showActivity)
                        userInfo: nil
                        repeats: YES];
    

这是实际更新标题的方法:

- (void)showActivity 

    NSString *sym = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];

    if (pauseInterval == nil) 

        // Update clock
        seconds = [[NSDate date] timeIntervalSinceDate:startInterval] - breakTime;

        // Update total earned
        secRate = rate.value / 60 / 60;
        total = secRate * seconds;
        [totalLabel setTitle:[NSString stringWithFormat:@"%@%.4f",sym,total] forState:UIControlStateNormal];

        days = seconds / (60 * 60 * 24);
        seconds -= days * (60 * 60 * 24);
        int hours = seconds / (60 * 60);
        fhours = (float)seconds / (60.0 * 60.0);
        seconds -= hours * (60 * 60);
        int minutes = seconds / 60;
        seconds -= minutes * 60;

        // Update the timer clock
        [elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
    

【问题讨论】:

它不应该闪烁。您是否尝试在后台线程上执行此操作? 是的,它被设置在一个计时器中以每秒更新一次按钮标题(我认为这是创建自己的线程) 定时器只有在你设置它们的情况下才能在单独的线程上运行。我们可以看看标题更新的方法以及您如何设置计时器吗? 我将请求的代码添加到主要问题 How to stop unwanted UIButton animation on title change?的可能重复 【参考方案1】:

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

【讨论】:

这确实应该是首选答案。最简单的解决方案。它的工作原理。 同意。我尝试了很多其他解决方案,这就是它自己完成的事情。 这应该是公认的答案。迄今为止最简单的解决方案。 像魅力一样工作!谢谢 我认为这是一个非常好的解决方案,无需为此编写任何代码。【参考方案2】:

[UIView setAnimationsEnabled:NO] 可能影响其他动画更好的方法是只禁用特定的标题动画。

目标-C:

[UIView performWithoutAnimation:^
  [myButton setTitle:text forState:UIControlStateNormal];
  [myButton layoutIfNeeded];
];

斯威夫特:

UIView.performWithoutAnimation  
    myButton.setTitle(text, for: .normal)
    myButton.layoutIfNeeded()

【讨论】:

刚刚在最新的 iOS 上尝试了 Swift 解决方案 - 效果很好。 救星。干杯! 刚刚在 Swift 3 中尝试过这个,它可以在不使用 layoutIfNeeded() 的情况下工作 这应该是毫无疑问的公认答案! 这是最好的方法。很好的答案!【参考方案3】:

*请注意*

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

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

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

【讨论】:

【参考方案4】:

查看How to stop unwanted UIButton animation on title change?的回复:

[UIView setAnimationsEnabled:NO];
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

【讨论】:

@FierceMonkey 尝试添加对layoutIfNeeded:[elapsed layoutIfNeeded]; 的呼叫。这消除了我的情况下的闪烁。 layoutIfNeeded 为我做了。 这似乎是一个相当肮脏的解决方法,但是 layoutIfNeeded 似乎正在工作【参考方案5】:

您可以简单地为 UIButton 制作另一个函数以方便将来使用。

extension UIButton 
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) 
        UIView.performWithoutAnimation 
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        
    

就是这样!

只需像以前一样设置标题,但将 setTitle 替换为 setTitleWithoutAnimation

【讨论】:

【参考方案6】:

默认的“setTitle”行为绝对是可恶的!

我的解决办法是:

[UIView setAnimationsEnabled:NO];
[_button layoutIfNeeded]; 
[_button setTitle:[NSString stringWithFormat:@"what" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

另外,在情节提要中,在按钮的属性下,我取消选中:

高光反转 突出显示的调整图像

然后检查:

禁用调整图像

iOS 8 上也经过测试和工作。

更新 - 斯威夫特

我建议您创建自定义按钮并覆盖 setTitle 方法。

class UnflashingButton: UIButton 
   
    override func setTitle(title: String?, forState state: UIControlState) 
        UIView.setAnimationsEnabled(false)
        self.layoutIfNeeded()
        super.setTitle(title, forState: state)
        UIView.setAnimationsEnabled(true)
    


【讨论】:

我尝试了这种方法(子类化、覆盖 setTitle:forState: 和禁用启用 UIView.setAnimationsEnabled)。在 iOS 9 和 10 测试版中不适合我。如果我只禁用动画,它就可以工作,但是每个 UIView 都会丢失它们......【参考方案7】:

试试这个,这适用于较新版本的 IOS:

class CustomButtonWithNoEffect : UIButton 
    override func setTitle(_ title: String?, for state: UIControlState) 
        UIView.performWithoutAnimation 
            super.setTitle(title, for: state)
            super.layoutIfNeeded()
        
    


【讨论】:

【参考方案8】:

我是编码和 *** 的新手,因此没有足够的声誉直接评论以扩展 https://***.com/users/4673064/daniel-tseng 出色的答案。所以我必须写我自己的新答案,就是这样:

extension UIButton 
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) 
        UIView.performWithoutAnimation 
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        
    

效果很好,除了:

如果我稍后在代码中对“setTitleWithoutAnimation”的所有调用都没有指定发件人,那么我会收到这些与 CoreMedia 或 CoreData 相关的奇怪消息,例如,“无法从 2526 继承 CoreMedia 权限:(null)”

这对于编码和 iOS 来说可能是非常基础的,但对于我作为一个新编码员来说,它让我在兔子路上走了一段时间,例如:Today Extension Failed to inherit CoreMedia permissions from,人们有有趣的答案,但没有达到我的问题的根源。

所以我终于发现我必须通过并给我的无参数函数参数,即我必须指定一个发送者。该发送者可以是 UIButton、Any 或 AnyObject。所有这些都有效,但最终似乎在添加带有“self”的按钮扩展名和稍后没有具体说明按钮正在使用它之间存在冲突。

再次,可能是基本的,但对我来说是新的,所以我认为它值得分享。

【讨论】:

【参考方案9】:

另一个技巧

@IBOutlet private weak var button: UIButton! 
    didSet 
        button.setTitle(title, for: .normal)
    

这只有在您知道标题的值而不进行任何 API 调用时才有效。按钮的标题将在视图加载之前设置,因此您不会看到动画

【讨论】:

以上是关于更新标题时如何防止UIButton闪烁的主要内容,如果未能解决你的问题,请参考以下文章

用户单击时如何禁用 UIButton 的突出显示

防止圆在 KineticJS 中闪烁

如何更改 UIButton 标题?

如何防止背景图像在更改时闪烁

如何防止自定义 UITableViewCells 在取消选择时闪烁白色?

UIButton 动作