タイトル変更時に不要なUIButtonアニメーションを停止する方法は?


211

iOS 7では、UIButtonのタイトルが間違った時間にアニメーション化され、遅くなります。この問題はiOS 6では発生しません。以下を使用しています。

[self setTitle:text forState:UIControlStateNormal];

私はこれが瞬時に、空白のフレームなしで行われることを望みます。この瞬きは特に注意をそらし、他のアニメーションから注意をそらします。


これも経験しています。それがiOS7のバグなのか、私たちが修正すべき何かなのかはわかりません。
2013

試してください。[self.button setHighlighted:NO];
karthika 2013

これらのアイデアをありがとう。私はsetHighlighted:NOを試しましたが、運がありません。内部にsetTitleを配置することで、瞬きを減らすことができます:[UIView animateWithDuration:0.0f animations:^ {...}];
exsulto 2013

1
この回避策は、次の場合に使用できますself.button.titleLabel.text = text。しかし、これはラベルフレームのサイズを変更せず、UIControlStatesで正しく機能しません
zxcat

それは賢い回避策です。これを試して、何が起こるかを確認します。残念ながら、UIControlStatesを使用しています。
exsulto 2013年

回答:


165

これはカスタムボタンで機能します。

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

システムボタンの場合、アニメーションを再度有効にする前にこれを追加する必要があります(@Klaasに感謝):

[_button layoutIfNeeded];

12
残念ながら、これは機能していないようです。また、withWithoutAnimation
Swayを

9
OK、つまり、最後に機能した修正は、元のUIButtonテキストを空白のままにして、コードで設定したときにアニメーションがトリガーされないようにすることでした。
2013年

27
これは、この回答に従って、ボタンのタイプをカスタムに設定した場合にのみ機能します。stackoverflow.com / a / 20718467 / 62
Liron Yahdav、2014

15
iOS 7.1以降、追加しなければなりませんでした[_button layoutIfNeeded];
Klaas

6
@LironYahdavボタンタイプをUIButtonTypeCustomに設定している場合、この回答は必要ありません。
DonnaLea 2014年

262

performWithoutAnimation:メソッドを使用して、後で強制的にレイアウトを強制的に実行します。

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

11
これは受け入れられた回答と同じように機能しますが、よりカプセル化されているため、見栄えがよくなります。[UIView setAnimationsEnabled:YES]を追加することを忘れたり、トラックから削除したりすることはできません。
siburb 2014年

19
[button layoutIfNeeded];ブロック内で呼び出すと、システムボタンに対して機能します。
Alexandre Blin

1
ところで、システムボタンの、layoutIfNeedを呼び出さなければなりませんした後にテキストが変更
ヨン

これが最善の解決策です!乾杯
sachadso

これは私にとって正しいものです。最も投票数が多く、6位です。ニース...
solgar

79

ボタンの種類をカスタムフォームインターフェイスビルダーに変更します。

ここに画像の説明を入力してください

これでうまくいきました。


6
最高のソリューション!ありがとうございました。
トーマスCalmon

3
しかし、これはクリックボタンのアニメーションも無効にします。ボタンの表示のアニメーションのみを無効にしたい。
Piotr Wasilewicz 2017

これは、ボタンがタップされたときのアニメーションを気にしない場合に機能します。
ホアキンペレイラ

私はいくつかのボタンをこのように設定しましたが、これは明らかに私の場合最もエレガントな答えです。よかった、ありがとう!
ゾルタン

79

Swiftでは次を使用できます:

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

1
これははるかに簡単な方法でした。そして、迅速な回答を含めていただきありがとうございます
シンプレキシティ

1
Swiftのベストアンサー!
Nubaslon 2017年

オフスクリーン中にUIButtonのタイトルを変更すると、interactivePopGestureRecognizerでアニメーションのタイミングがおかしくなるという厄介なバグがあり、これで解決しました。それでもOSのバグだと思います
SparkyRobinson '

奇妙なことに.layoutIfNeeded()を呼び出す必要がありますが、Swift 5で両方の方法でテストしましたが、それなしでも確実にアニメーション化されます。
wildcat12

2
あんまり。電話しないとlayoutIfNeeded()、ボタンが再描画をする必要があるものとしてフラグが立てられているが、これは外になり、次のレイアウトパス、までは発生しませんperformWithoutAnimation
Paulw11

60

ご注意ください :

_buttonのbuttonType」が「UIButtonTypeSystem」の場合、以下のコードは無効です:

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

いつ "_buttonの buttonType "が"UIButtonTypeCustom"の場合、上記のコードは有効です


ボタンの種類を変更するだけでよいと思うまでにどれだけの時間を費やしたか信じられない...うーん...
Sandy Chapman

コードなしで動作します。ボタンの種類のみを変更すれば機能します。
Alex Motor

52

iOS 7.1以降、私にとって機能する唯一の解決策は、ボタンをtypeで初期化することでしたUIButtonTypeCustom


これは、UIButtonTypeSystemを必要としない人にとって最も賢明なアプローチです。
DonnaLea 2014年

これが私にとって最も効果的な方法でした。CUSTOMボタンを作成し、システムボタンのように表示および強調表示しました。違いはほとんどわかりませんが、遅れはありません。
Travis M.

18

だから私は働いた解決策を見つけます:

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

最初にボタンのタイトルを変更し、次にこのタイトルのボタンのサイズを変更します


1
同じ回避策を使用します。受け入れられた答えは私にとってはうまくいきません。
deej 2014

これは、少なくともiOSの8で、タイトルが二回点滅します
ヨルダンH

1
これは、フラッシュなしで7.1と8.1の両方で動作します。シンプルで効果的。
トッド、

iOS 11では完全に機能しますが、2行目に同じ文字列を再度使用する必要がありました(ボタンラベルのタイトルを使用すると、点滅しました)。
SilverWolf-モニカを復活させる'19年

13

ボタンタイプをUIButtonTypeCustomに設定すると、点滅が停止します


この単純な答えがこの問題を99%の時間で解決しなければならないときに、これらのすべての回避策「ソリューション」が非常に多くの賛成票を持つことができます...
Rob

12

スウィフト5

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

これが機能する理由はわかりませんが、機能し、最もクリーンなソリューションです。UIKitは奇妙です。
Nathan Hosselton

11

これを行うために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で同様です)


今は使うつもりはありませんが、持っておくととても重宝します!
フランシスレイノルズ

9

UIButtonタイプをカスタムに設定します。これにより、フェードインとフェードアウトのアニメーションが削除されます。


1
これにはもっと賛成票があるはずです!他の回避策の代わりに、完全に機能し、根本原因のアニメーションを無効にします。
JesperSchläger19年

7

通常、ボタンの種類をカスタムに設定するだけでうまくいきますが、他の理由により、UIButtonをサブクラス化してボタンの種類をデフォルト(システム)に戻す必要があったため、点滅が再表示されました。

UIView.setAnimationsEnabled(false)タイトルを変更する前に設定し、その後再びtrueに設定しても、電話をかけたかどうかに関係なく、点滅は回避されませんでしたself.layoutIfNeeded()でした。

これは、次の正確な順序でのみ、iOS 9および10ベータで動作しました。

1)UIButtonのサブクラスを作成します(ストーリーボードでもボタンのカスタムクラスを設定することを忘れないでください)。

2)setTitle:forState:次のようにオーバーライドします。

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

Interface Builderでは、ボタンのタイプをSystemのままにしておくことができます。このアプローチを機能させるためにボタンタイプをカスタムタイプに変更する必要はありません。

これが他の人の役に立つことを願っています。迷惑な点滅ボタンで他の人にそれを避けたいと長い間苦労してきました;)


忘れないでくださいlayoutIfNeeded():]
Tai Le

6

カスタムボタンを作成するだけで、タイトルの変更中にアニメーションが停止します。

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

ストーリーボードのチェックボックスでも実行できます。ストーリーボードのボタンを選択します->属性インスペクタを選択します(左側から4番目)-> [タイプ]ドロップダウンメニューで、おそらく選択されていた[システム]ではなく[カスタム]を選択します。

幸運を!



3

Xhacker LiuのSwift 4バージョンの回答

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 

1

systemタイプのUIButtonには、暗黙的なアニメーションがありsetTitle(_:for:)ます。次の2つの方法で修正できます。

  1. customコードまたはインターフェイスビルダーから、ボタンタイプをに設定します。
let button = UIButton(type: .custom)

ここに画像の説明を入力してください

  1. コードからアニメーションを無効にする:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}

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)


この回避策がiOS 7.1では機能しないことを確認しました。
sCha 2014年

7.1の解決策を見つけたと思いませんか?
ジョージグリーン

@GeorgeGreenはUIButtonTypeSystemの有効なソリューションを見つけることができませんでした。UIButtonTypeCustomを使用する必要がありました。
sCha 2014年

7.1以降、すべての状態にタイトルの変更を適用する必要があります。通常の状態にのみ設定すると、適用されなくなります。[_button setTitle:@"title" forState:UIControlStateDisabled]
サム

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];
}

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];
    }

}

理想的ではありませんが、動作します。


0

実際にアニメーションブロックの外でタイトルを設定できます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()
}

0

Xhacker Liu拡張機能がSwift 3に変換されました。

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

-1

おそらく、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;}];

-1

私はそれを組み合わせて動作させることができました:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];

-1

デフォルトの実装でうまく機能する、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のAPIと一致していますUIButton
Richard Topchii
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.