Başlık değişikliğinde istenmeyen UIButton animasyonu nasıl durdurulur?


211

İOS 7'de UIButton başlıklarım yanlış zamanda giriş ve çıkış yapıyor. Bu sorun iOS 6'da görünmüyor. Sadece kullanıyorum:

[self setTitle:text forState:UIControlStateNormal];

Bunun anında ve boş bir çerçeve olmadan olmasını tercih ederim. Bu göz kırpma özellikle dikkat dağıtıcıdır ve diğer animasyonlardan dikkati çeker.


Bunu da deneyimliyoruz. Bir iOS7 hatası mı yoksa düzeltmemiz gereken bir şey mi olduğundan emin değilim.
Sallanma

Deneyin, [self.düğmesi seti Vurgulanan: HAYIR];
karthika

Bu fikirler için teşekkürler. Ben setHighlighted: HAYIR, ama orada şans yok. SetTitle içine yerleştirerek yanıp sönmeyi azaltabiliyorum: [UIView animateWithDuration: 0.0f animations: ^ {...}];
exsulto

1
Bazı durumlarda bu geçici çözümü kullanabilirsiniz: self.button.titleLabel.text = text. Ancak bu etiket çerçevesini yeniden boyutlandırmaz ve
UIControlStates

Bu akıllıca bir çözüm. Bununla oynayacağım ve ne olacağını göreceğim, maalesef UIControlStates kullanıyorum.
exsulto

Yanıtlar:


165

Bu, özel düğmeler için çalışır:

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

Sistem düğmeleri için, animasyonları yeniden etkinleştirmeden önce bunu eklemeniz gerekir (teşekkür ederim @Klaas):

[_button layoutIfNeeded];

12
Ne yazık ki bu işe yaramıyor. Animasyon Yok
Sway

9
Tamam, bu yüzden sonunda çalışan düzeltme, orijinal UIButton metnini boş bırakmaktı, böylece kodla ayarladığımda animasyonu tetiklemiyordu.
Sway

27
Bu yalnızca, bu cevaba göre düğmenin türünü özel olarak ayarlarsanız çalışır stackoverflow.com/a/20718467/62 .
Liron Yahdav

15
İOS 7.1'den itibaren eklemek zorunda kaldım[_button layoutIfNeeded];
Klaas

6
@LironYahdav, düğme türü UIButtonTypeCustom olarak ayarlandıysa, bu yanıt gerekli değildir.
DonnaLea

262

performWithoutAnimation:Yöntemi kullanın ve ardından mizanpajı daha sonra değil hemen gerçekleşmeye zorlayın.

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

11
Bu, kabul edilen yanıtın yanı sıra çalışır, ancak daha kapsüllenmiş olduğu için daha hoş görünür - [UIView setAnimationsEnabled: YES] eklemeyi veya parçanın kaldırılmasını unutmak imkansızdır.
siburb

19
[button layoutIfNeeded];Blok içinde ararsanız sistem düğmeleri için çalışır .
Alexandre Blin

1
BTW, sistem düğmeleri için, metin değiştirildikten sonra layoutIfNeed çağrılmalıdır
Yon

Bu en iyi çözüm! Şerefe
sachadso

Bu benim için doğru olanı. En çok oy alan ve 6. sırada. Güzel ...
solgar

79

Düğme türünü özel form arabirimi oluşturucu olarak değiştirin.

resim açıklamasını buraya girin

Bu benim için çalıştı.


6
En iyi çözüm! Teşekkür ederim.
Thomás Calmon

3
Ancak bu, tıklama düğmesindeki animasyonu da devre dışı bırakır. Animasyonu yalnızca gösterilen düğmede devre dışı bırakmak istiyorum.
Piotr Wasilewicz

Düğmeye dokunulduğunda animasyonu umursamıyorsanız bu işe yarar.
Joaquin Pereira

Bu şekilde ayarlanmış birkaç düğme yaşadım ve bu benim durumum için en zarif cevap. Güzel, teşekkürler!
Zoltán

79

Swift'te şunları kullanabilirsiniz:

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

1
Bu, en kolay yöntemdi. Ve hızlı bir cevap btw
eklediğiniz

1
Swift için en iyi cevap!
Nubaslon

Ekran dışındayken bir UIButton başlığını değiştirmenin interaktifPopGestureRecognizer ile garip animasyon zamanlamalarına neden olacağı ve sinir bozucu bir hata vardı. Yine de işletim sistemi ile ilgili bir hata olduğunu düşünüyorum
SparkyRobinson

Garip .layoutIfNeeded () çağrılmalıdır, ancak Swift 5'te her iki şekilde de test ettim ve kesinlikle onsuz animasyon yapıyor.
wildcat12

2
Pek sayılmaz. Eğer aramazsan layoutIfNeeded()sonra düğme yeniden çizilmesi gerek şeklinde işaretlenmiş ancak bu dış olacaktır sonraki düzen geçişte kadar olmayacakperformWithoutAnimation
Paulw11

60

Lütfen aklınızda bulundurun :

_düğmesinin " buttonType " öğesi "UIButtonTypeSystem" olduğunda , aşağıdaki kod geçersiz

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

_düğmesinin " buttonType " öğesi "UIButtonTypeCustom" olduğunda , yukarıdaki kod geçerlidir .


Sadece düğme türünü değiştirmen gerektiğini anlamaya başlamadan önce ne kadar zaman harcadığına inanamıyorum ... ugh ...
Sandy Chapman

Herhangi bir kod olmadan çalışır. Yalnızca düğme türünü değiştirdiğinizde çalışır.
Alex Motor

52

İOS 7.1'den başlayarak benim için çalışan tek çözüm düğmeyi türüyle başlatmaktı UIButtonTypeCustom.


Bu, UIButtonTypeSystem gerektirmeyen herkes için en mantıklı yaklaşımdır.
DonnaLea

Bu benim için en iyi sonucu verdi, sadece bir ÖZEL düğmesi oluşturdum ve bir sistem düğmesi gibi görünmesini ve vurgulanmasını sağladım. Farkı zor görüyorum ama bu gecikmeye sahip değilsiniz.
Travis M.

18

bu yüzden çalışan bir çözüm bulmak:

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

önce düğmenin başlığını değiştiririz, sonra bu başlık için yeniden boyutlandırırız


1
Aynı geçici çözümü kullanıyorum. Kabul edilen cevap benim için çalışmıyor.
deej

Bu, başlığın en az iOS 8 ile iki kez yanıp sönmesine neden olur.
Jordan H

1
Bu benim için 7.1 ve 8.1'de yanıp sönmeden çalışıyor. Basit ve etkili.
Todd

Aynı dizeyi ikinci satır için tekrar kullanmam gerekmesine rağmen iOS 11'de mükemmel çalışıyor (düğme etiketinin başlığını kullanarak yanıp sönmesine neden oldu).
SilverWolf - Monica'yı

13

Düğme türünü UIButtonTypeCustom olarak ayarlayın, yanıp sönmeyi durdurur


Bu basit yanıtın bu sorunu% 99 oranında çözmesi gerektiğinde tüm bu geçici çözümlerin "çözümleri" ne kadar çok oy verebilir?
Rob

12

Hızlı 5

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

Bunun neden çalıştığını bilmiyorum ama işe yarıyor ve en temiz çözüm. UIKit garip.
Nathan Hosselton

11

Bunu yapmak için bir Swift uzantısı yaptım:

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

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Benim için iOS 8 ve 9'da çalışıyor UIButtonTypeSystem.

(Kod Swift 2, Swift 3 ve Objective-C için benzer olmalıdır)


Şimdi kullanmayacaksınız ama çok kullanışlı!
Francis Reynolds

9

UIButton türünü Özel olarak ayarlayın. Bu, solma giriş ve çıkış animasyonlarını kaldırmalıdır.


1
Bu daha fazla oy olmalı! Mükemmel çalışır ve diğer geçici çözümler yerine animasyonu kök nedente devre dışı bırakır.
Jesper Schläger

7

Genellikle düğme türünü Özel olarak ayarlamak benim için çalışır, ancak başka nedenlerle UIButton'u alt sınıflamak ve düğme türünü tekrar varsayılan (Sistem) olarak ayarlamak zorunda kaldım, böylece yanıp sönme tekrar ortaya çıktı.

UIView.setAnimationsEnabled(false)Başlığı değiştirmeden önce ayarlamak ve daha sonra tekrar doğru yapmak, aramamdan self.layoutIfNeeded()ya da aramamdan bağımsız olarak benim için yanıp sönmeyi engellemedi .

Bu ve sadece aşağıdaki sırayla, iOS 9 ve 10 beta ile benim için çalıştı:

1) UIButton için bir alt sınıf oluşturun (Storyboard'daki düğme için özel sınıfı da ayarlamayı unutmayın).

2) setTitle:forState:Aşağıdaki gibi geçersiz kılın :

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

Interface Builder'da, bu yaklaşımın çalışması için düğme türünü Sistem olarak bırakabilirsiniz, Özel Tür olarak değiştirmenize gerek yoktur.

Umarım bu başka birine yardımcı olur, sinir bozucu yanıp sönen düğmelerle o kadar uzun süre mücadele ettim ki başkalarına kaçınmayı umuyorum;)


Unutmayın layoutIfNeeded():]
Tai Le

6

Özel düğme oluşturabilirsiniz, başlık değiştirilirken animasyon durdurulacaktır.

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

Storyboard onay kutusunda da yapabilirsiniz: film şeridindeki düğmeyi seçin -> nitelik denetçisini seçin (sol taraftan dördüncü) -> 'Tür' açılır menüsünde, muhtemelen seçilen 'Sistem' yerine 'Özel'i seçin .

İyi şanslar!


3

Animasyonları başlık etiketinin katmanından kaldırabilirsiniz:

    [[[theButton titleLabel] layer] removeAllAnimations];

Bütün cevapları verdim. Bu en iyisi.
Rudolf Adamkovič

2
Hala yanıp sönüyor ama daha iyi.
Lucien

BU CEVAP OLMALIDIR.
mxcl

3

Xhacker Liu cevabının Swift 4 versiyonu

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 

1

UIButton systemtüründe açık animasyon var setTitle(_:for:). Bunu iki farklı şekilde düzeltebilirsiniz:

  1. Düğme türünü customkoddan veya Arayüz Oluşturucu'dan olarak ayarlayın:
let button = UIButton(type: .custom)

resim açıklamasını buraya girin

  1. Animasyonu koddan devre dışı bırak:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}

0

Bu geçici çözümün UIButtonTypeSystem ile de çalıştığını, ancak yalnızca düğme herhangi bir nedenle etkinleştirilirse çalışacağını buldum .

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

Bu nedenle, başlığını ayarlarken düğmenin devre dışı bırakılması gerekiyorsa bunları eklemeniz gerekir.

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

(iOS 7, Xcode 5)


Bu geçici çözümün artık iOS 7.1'de çalışmadığını doğruladık.
sCha

7.1 için bir çözüm bulduğunuzu düşünmüyor musunuz?
George Green

@GeorgeGreen, UIButtonTypeSystem için herhangi bir çalışma çözümü bulamadı . UIButtonTypeCustom kullanmak zorundaydım .
sCha

7.1'den bu yana, tüm durumlara başlık değişiklikleri uygulamanız gerekir; yalnızca normal durum için geçerli değildir. [_button setTitle:@"title" forState:UIControlStateDisabled]
Sam

0

Yukarıdaki harika yanıtların birleştirilmesi, UIButtonTypeSystem için aşağıdaki geçici çözümle sonuçlanır :

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

Bir UITabBarController içinde görünüm denetleyicilerinde düğme başlıklarını değiştirirken çirkin animasyon sorunu var. Başlangıçta film şeridinde belirlenen başlıklar, yeni değerlerine geçmeden kısa bir süre önce ortaya çıktı.

Tüm alt görünümleri yineleme ve NSLocalizedString ile yerelleştirilmiş değerlerini almak için düğme başlıklarını anahtarlar olarak kullanmak istedim;

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

}

Animasyonu tetikleyen şeyin gerçekten btn.titleLabel.text çağrısı olduğunu öğrendim. Öyleyse yine de storyboard'ları kullanmak ve bileşenlerin bu şekilde dinamik olarak yerelleştirilmesini sağlamak için her düğmenin Restoration ID'sini (Identity Inspector'da) başlıkla aynı şekilde ayarladığınızdan ve bunu başlık yerine anahtar olarak kullandığınızdan emin olun;

for(UIView *v in view.subviews) {

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

}

İdeal değil ama çalışıyor ..


0

Başlığı bir animasyon bloğunun dışında ayarlayabilir, yalnızca layoutIfNeeded()bir gerçekleştirmenin içinde aradığınızdan emin olun :

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()
}

Bir grup düğmeniz varsa, yalnızca layoutIfNeeded()süper görünümü aramayı düşünün :

button1.setTitle("abc", forState: .Normal)
button2.setTitle("abc", forState: .Normal)
button3.setTitle("abc", forState: .Normal)
UIView.performWithoutAnimation {
    self.view.layoutIfNeeded()
}

0

Xhacker Liu uzantısı Swift 3'e dönüştürüldü:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

-1

Bir düğmenin metnini canlandırma ve değiştirme ile ortaya çıkan sorunu önlemek için belki 2 animasyon ve 2 düğme oluşturmak daha iyi bir çözümdür?

İkinci bir uibutton oluşturdum ve 2 animasyon oluşturdum, bu çözüm hiçbir hickup olmadan çalışıyor.

    _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

Bir cevap kombinasyonu ile çalıştım:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];

-1

Swift'te varsayılan uygulama ile güzel oynayan animasyonlu düğme başlığı değişikliği için uygun bir uzantı:

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. Cevabım farklı 2. Güncel Swift sözdizimi 3. Apple'ın API'sı ile uyumlu UIButton.
Richard Topchii
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.