如何在标题更改时停止不需要的 UIButton 动画?
Posted
技术标签:
【中文标题】如何在标题更改时停止不需要的 UIButton 动画?【英文标题】:How to stop unwanted UIButton animation on title change? 【发布时间】:2013-09-27 14:18:27 【问题描述】:在 ios 7 中,我的 UIButton 标题在错误的时间进出动画 - 延迟。这个问题在 iOS 6 上没有出现。我只是在使用:
[self setTitle:text forState:UIControlStateNormal];
我希望这种情况立即发生并且没有空白框。这种眨眼尤其会分散注意力,并将注意力从其他动画上移开。
【问题讨论】:
我们也遇到了这种情况。不确定这是 iOS7 的错误还是我们应该修复的问题。 试试,[self.button setHighlighted:NO]; 感谢这些想法。我试过 setHighlighted:NO,但没有运气。我可以通过将 setTitle 放在里面来减少眨眼: [UIView animateWithDuration:0.0f animations:^ ... ]; 您可以在某些情况下使用此解决方法:self.button.titleLabel.text = text
。但这不会调整标签框架的大小,也不能正确使用 UIControlStates
这是一个聪明的解决方法。我会玩这个,看看会发生什么,不幸的是我正在使用 UIControlStates。
【参考方案1】:
使用performWithoutAnimation:
方法,然后强制布局立即发生,而不是稍后发生。
[UIView performWithoutAnimation:^
[self.myButton setTitle:text forState:UIControlStateNormal];
[self.myButton layoutIfNeeded];
];
【讨论】:
这与公认的答案一样有效,但似乎更好,因为它更加封装 - 不可能忘记添加 [UIView setAnimationsEnabled:YES],或者将其从轨道上删除. 如果您在块内调用[button layoutIfNeeded];
,它适用于系统按钮。
顺便说一句,对于系统按钮,layoutIfNeed 应该在 文本更改后调用
这是最好的解决方案!干杯
这对我来说是正确的。它的投票最多,排在第 6 位。不错...【参考方案2】:
这适用于自定义按钮:
[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
对于系统按钮,您需要在重新启用动画之前添加它(谢谢@Klaas):
[_button layoutIfNeeded];
【讨论】:
不幸的是,这似乎不起作用。 performWithoutAnimation 也没有 好的,所以最终的解决方法是将原始 UIButton 文本留空,这样当我用代码设置它时它不会触发动画。 这仅在您将按钮的类型设置为自定义时才有效,根据此答案***.com/a/20718467/62。 从 iOS 7.1 开始,我必须添加[_button layoutIfNeeded];
@LironYahdav 如果您将按钮类型设置为 UIButtonTypeCustom,则不需要此答案。【参考方案3】:
在 Swift 中你可以使用:
UIView.performWithoutAnimation
self.someButtonButton.setTitle(newTitle, forState: .normal)
self.someButtonButton.layoutIfNeeded()
【讨论】:
这是迄今为止最简单的方法。并感谢您提供一个快速的回答顺便说一句 Swift 的最佳答案! 有一个烦人的错误,即在屏幕外更改 UIButton 标题会导致使用 interactivePopGestureRecognizer 产生奇怪的动画计时,这解决了它。我仍然认为这是操作系统的错误 奇怪的是 .layoutIfNeeded() 必须被调用,但我在 Swift 5 中对它进行了两种测试,没有它它肯定仍然可以动画。 并非如此。如果您不调用layoutIfNeeded()
,则该按钮将被标记为需要重绘,但这要等到下一个布局通过之后才会发生,这将在performWithoutAnimation
之外。【参考方案4】:
将按钮类型更改为自定义表单界面生成器。
这对我有用。
【讨论】:
最佳解决方案!谢谢。 但这也会禁用点击按钮上的动画。我只想在显示按钮时禁用动画。 如果您不关心点击按钮时的动画效果,则此方法有效。 我已经设置了几个这样的按钮,显然这对我的案例来说是最优雅的答案。很好,谢谢!【参考方案5】:请注意:
当_button的“buttonType”为“UIButtonTypeSystem”时,下面的代码无效:
[UIView setAnimationsEnabled:NO];
[_button setTitle:@"title" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];
当_button的“buttonType”为“UIButtonTypeCustom”时,上述代码为有效。
【讨论】:
不敢相信我花了多少时间才弄清楚你只需要更改按钮类型......呃...... 无需任何代码即可工作。只需更改按钮类型即可。【参考方案6】:从 iOS 7.1 开始,唯一对我有用的解决方案是使用 UIButtonTypeCustom
类型初始化按钮。
【讨论】:
这对于不需要 UIButtonTypeSystem 的人来说是最明智的方法。 这对我来说效果最好,我刚刚创建了一个 CUSTOM 按钮,让它看起来像系统按钮一样突出显示。几乎看不出区别,但你没有那种延迟。【参考方案7】:斯威夫特 5
myButton.titleLabel?.text = "title"
myButton.setTitle("title", for: .normal)
【讨论】:
不知道为什么会这样,但它确实有效,而且它是最干净的解决方案。 UIKit 很奇怪。 不,它不是一个干净的解决方案,但它很脏,因为这可能会随任何 iOS 改变 @NathanHosselton 查看 dubenko 在 2014 年 4 月 22 日的回答。 “首先我们更改按钮的标题,然后调整此标题的按钮大小”【参考方案8】:所以我找到了可行的解决方案:
_logoutButton.titleLabel.text = NSLocalizedString(@"Logout",);
[_logoutButton setTitle:_logoutButton.titleLabel.text forState:UIControlStateNormal];
首先我们更改按钮的标题,然后调整此标题的按钮大小
【讨论】:
我使用相同的解决方法。接受的答案对我不起作用。 这会导致标题闪烁两次,至少在 iOS 8 中是这样。 这在 7.1 和 8.1 中都适用于我,无需闪烁。简单有效。 在 iOS 11 中完美运行,尽管我不得不在第二行再次使用相同的字符串(使用按钮标签的标题导致它闪烁)。【参考方案9】:将按钮类型设置为 UIButtonTypeCustom,它将停止闪烁
【讨论】:
当这个简单的答案必须在 99% 的时间里解决这个问题时,所有那些变通的“解决方案”怎么会有这么多的赞成票......【参考方案10】:我为此做了一个 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】:system
类型的 UIButton 在 setTitle(_:for:)
上具有隐式动画。您可以通过两种不同的方式修复它:
-
通过代码或 Interface Builder 将按钮类型设置为
custom
:
let button = UIButton(type: .custom)
-
从代码中禁用动画:
UIView.performWithoutAnimation
button.setTitle(title, for: .normal)
button.layoutIfNeeded()
【讨论】:
【参考方案12】:将 UIButton 类型设置为自定义。这应该会移除淡入淡出动画。
【讨论】:
这应该有更多的赞成票!完美运行并从根本原因禁用动画,而不是这些其他解决方法。【参考方案13】:通常简单地将按钮类型设置为自定义对我来说是可行的,但由于其他原因,我需要子类化 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 即可使用此方法。
我希望这对其他人有所帮助,我已经为烦人的闪烁按钮苦苦挣扎了很长时间,我希望避免对其他人造成影响;)
【讨论】:
别忘了layoutIfNeeded()
:]【参考方案14】:
您可以简单地创建自定义按钮,它会在更改标题时停止动画。
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"the title" forState:UIControlStateNormal];
您也可以在 Storyboard 复选框中执行此操作: 选择情节提要中的按钮 -> 选择属性检查器(左起第四个)-> 在“类型”下拉菜单中,选择“自定义”而不是可能选择的“系统”。
祝你好运!
【讨论】:
【参考方案15】:Swift 4 版 Xhacker 刘回答
import Foundation
import UIKit
extension UIButton
func setTitleWithOutAnimation(title: String?)
UIView.setAnimationsEnabled(false)
setTitle(title, for: .normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
【讨论】:
【参考方案16】:您可以从标题标签的图层中删除动画:
[[[theButton titleLabel] layer] removeAllAnimations];
【讨论】:
我浏览了所有答案。这个是最好的。 它仍然在闪烁,但已经更好了。 这应该是答案。【参考方案17】:您实际上可以在动画块之外设置标题,只要确保在 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()
【讨论】:
【参考方案18】:我发现此解决方法也适用于 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)
【讨论】:
刚刚确认此解决方法不再适用于 iOS 7.1。 不认为你已经找到了 7.1 的解决方案? @GeorgeGreen 找不到任何适用于 UIButtonTypeSystem 的解决方案。我不得不使用 UIButtonTypeCustom。 自 7.1 起,您需要将标题更改应用到所有状态,将其设置为仅适用于正常状态不再适用。[_button setTitle:@"title" forState:UIControlStateDisabled]
【参考方案19】:
结合以上出色的答案,可以为 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];
【讨论】:
【参考方案20】:在 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];
不理想,但有效..
【讨论】:
【参考方案21】:Xhacker Liu 扩展转换为 Swift 3:
extension UIButton
func setTitleWithoutAnimation(title: String?)
UIView.setAnimationsEnabled(false)
setTitle(title, for: .normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
【讨论】:
【参考方案22】:一个方便的 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)
【讨论】:
@Fogmeister 1. 我的答案不同 2. 最新的 Swift 语法 3. 与 Apple 的UIButton
API 一致。【参考方案23】:
我得到了它的答案组合:
[[[button titleLabel] layer] removeAllAnimations];
[UIView performWithoutAnimation:^
[button setTitle:@"Title" forState:UIControlStateNormal];
];
【讨论】:
【参考方案24】:也许生成 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;];
【讨论】:
以上是关于如何在标题更改时停止不需要的 UIButton 动画?的主要内容,如果未能解决你的问题,请参考以下文章