Bagaimana cara menghentikan animasi UIButton yang tidak diinginkan saat perubahan judul?

211

Di iOS 7 judul UIButton saya bergerak masuk dan keluar pada waktu yang salah - terlambat. Masalah ini tidak muncul di iOS 6. Saya hanya menggunakan:

[self setTitle:text forState:UIControlStateNormal];

Saya lebih suka ini terjadi secara instan dan tanpa bingkai kosong. Kedipan ini sangat mengganggu dan menarik perhatian dari animasi lain.

exsulto
sumber
Kami juga mengalami ini. Tidak yakin apakah itu bug iOS7 atau sesuatu yang harus kami perbaiki.
Sway
Coba, [set.button otomatis disorot: TIDAK];
karthika
Terima kasih atas ide-ide ini. Saya mencoba setHighlighted: TIDAK, tetapi tidak berhasil di sana. Saya dapat mengurangi kedipan dengan menempatkan setTitle di dalam: [UIView animateWithDuration: animasi 0.0f: ^ {...}];
exsulto
1
Anda dapat menggunakan solusi ini dalam beberapa kasus: self.button.titleLabel.text = text. Tapi ini tidak mengubah ukuran bingkai label dan tidak bekerja dengan UIControlStates dengan benar
zxcat
Itu solusi cerdas. Saya akan bermain dengan ini dan melihat apa yang terjadi, sayangnya saya menggunakan UIControlStates.
exsulto

Jawaban:

165

Ini berfungsi untuk tombol khusus:

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

Untuk tombol sistem Anda perlu menambahkan ini sebelum mengaktifkan kembali animasi (terima kasih @Klaas):

[_button layoutIfNeeded];
Jacob K
sumber
12
Sayangnya ini sepertinya tidak berhasil. Tidak melakukan Performa Tanpa
Sway
9
Ok, jadi perbaikan yang berhasil pada akhirnya adalah membiarkan teks UIButton asli kosong sehingga ketika saya mengaturnya dengan kode itu tidak memicu animasi.
Goyang
27
Ini hanya berfungsi jika Anda mengatur jenis tombol ke kustom, sesuai jawaban ini stackoverflow.com/a/20718467/62 .
Liron Yahdav
15
Pada iOS 7.1 saya harus menambahkan[_button layoutIfNeeded];
Klaas
6
@LironYahdav jika Anda memiliki jenis tombol yang diatur ke UIButtonTypeCustom, maka jawaban ini tidak diperlukan.
DonnaLea
262

Gunakan performWithoutAnimation:metode dan kemudian memaksa tata letak terjadi segera, bukan nanti.

[UIView performWithoutAnimation:^{
  [self.myButton setTitle:text forState:UIControlStateNormal];
  [self.myButton layoutIfNeeded];
}];
Manusia salju
sumber
11
Ini berfungsi baik sebagai jawaban yang diterima, tetapi tampaknya lebih baik karena lebih dienkapsulasi - tidak mungkin untuk lupa menambahkan [UIView setAnimationsEnabled: YA], atau untuk itu agar dihapus di trek.
siburb
19
Ini berfungsi untuk tombol sistem jika Anda memanggil [button layoutIfNeeded];bagian dalam blok.
Alexandre Blin
1
BTW, untuk tombol sistem, layoutIfNeed harus dipanggil setelah teks berubah
Yon
Ini solusi terbaik! Cheers
sachadso
Ini benar untuk saya. Itu yang paling banyak dipilih dan di tempat ke-6. Bagus ...
solgar
79

Ubah jenis tombol ke pembuat antarmuka bentuk kustom.

masukkan deskripsi gambar di sini

Ini berhasil untuk saya.

Christos Chadjikyriacou
sumber
6
Solusi terbaik! Terima kasih.
Thomás Calmon
3
Tetapi ini juga menonaktifkan animasi pada tombol klik. Saya hanya ingin menonaktifkan animasi pada tombol pertunjukan.
Piotr Wasilewicz
Ini berfungsi jika Anda tidak peduli dengan animasi ketika tombol diketuk.
Joaquin Pereira
Saya sudah memiliki beberapa tombol yang diatur seperti ini dan jelas ini adalah jawaban paling elegan untuk kasus saya. Terima kasih banyak!
Zoltán
79

Di Swift Anda dapat menggunakan:

UIView.performWithoutAnimation {
    self.someButtonButton.setTitle(newTitle, forState: .normal)
    self.someButtonButton.layoutIfNeeded()
}
Paulw11
sumber
1
Sejauh ini, ini adalah metode termudah. Dan terima kasih sudah menyertakan jawaban cepat btw
simpleksitas
1
Jawaban terbaik untuk Swift!
Nubaslon
Mengalami bug yang menjengkelkan ketika mengubah judul UIButton sementara offscreen akan menyebabkan timing animasi aneh dengan interactivePopGestureRecognizer dan ini menyelesaikannya. Saya masih berpikir itu adalah bug dengan OS sekalipun
SparkyRobinson
Aneh bahwa .layoutIfNeeded () harus dipanggil, tapi saya mengujinya dengan dua cara di Swift 5 dan pasti masih menjiwai tanpanya.
wildcat12
2
Tidak juga. Jika Anda tidak menelepon layoutIfNeeded()maka tombol ditandai sebagai perlu digambar ulang tetapi ini tidak akan terjadi sampai tata letak berikutnya berlalu, yang akan berada di luarperformWithoutAnimation
Paulw11
60

Tolong dicatat :

ketika " buttonType " dari _button adalah "UIButtonTypeSystem" , kode di bawah ini tidak benar

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

ketika " buttonType " dari _button adalah "UIButtonTypeCustom" , kode di atas valid .

shede333
sumber
Tidak percaya berapa banyak waktu yang saya habiskan sebelum mencari tahu Anda hanya perlu mengubah jenis tombol ... ugh ...
Sandy Chapman
Bekerja tanpa kode apa pun. Ubah hanya jenis tombol dan itu akan berhasil.
Alex Motor
52

Mulai di iOS 7.1 satu-satunya solusi yang bekerja untuk saya adalah menginisialisasi tombol dengan tipe UIButtonTypeCustom.

Norbert
sumber
Ini adalah pendekatan yang paling masuk akal bagi siapa pun yang tidak memerlukan UIButtonTypeSystem.
DonnaLea
Ini akhirnya bekerja paling baik untuk saya, saya baru saja membuat tombol KUSTOM dan membuatnya terlihat dan disorot seperti tombol sistem. Hampir tidak dapat melihat perbedaannya tetapi Anda tidak memiliki penundaan itu.
Travis M.
18

jadi saya menemukan solusi yang berhasil:

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

pertama kita mengubah judul untuk tombol, lalu mengubah ukuran tombol untuk judul ini

dubenko
sumber
1
Saya menggunakan solusi yang sama. Jawaban yang diterima tidak berhasil untuk saya.
deej
Hal ini menyebabkan judul untuk berkedip dua kali, setidaknya dengan iOS 8.
Jordan H
1
Ini bekerja untuk saya di 7.1 dan 8.1 tanpa berkedip. Sederhana dan efektif.
Todd
Berfungsi sempurna di iOS 11, meskipun saya harus menggunakan string yang sama lagi untuk baris kedua (menggunakan judul label tombol menyebabkannya berkedip).
SilverWolf - Pasang kembali Monica
13

Setel jenis tombol ke UIButtonTypeCustom dan itu akan berhenti berkedip

arunjos007
sumber
Bagaimana semua solusi "solusi" ini dapat memiliki begitu banyak upvotes ketika jawaban sederhana ini harus menyelesaikan masalah ini 99% setiap saat ...
Rob
12

Cepat 5

myButton.titleLabel?.text = "title"
myButton.setTitle("title", for: .normal)
Carter Randall
sumber
Tidak tahu mengapa ini berhasil tetapi itu berhasil dan itu adalah solusi terbersih. UIKit aneh.
Nathan Hosselton
11

Saya telah membuat ekstensi Swift untuk melakukan ini:

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

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Bekerja untuk saya di iOS 8 dan 9, dengan UIButtonTypeSystem.

(Kode untuk Swift 2, Swift 3 dan Objective-C harus serupa)

Xhacker Liu
sumber
Tidak akan menggunakannya sekarang tetapi sangat berguna untuk berkeliling!
Francis Reynolds
9

Tetapkan jenis UIButton sebagai Kustom. Itu harus menghapus animasi fade in dan out.

Amit Tandel
sumber
1
Ini harus memiliki lebih banyak suara positif! Berfungsi dengan sempurna dan menonaktifkan animasi pada akar permasalahan, alih-alih solusi lain ini.
Jesper Schläger
7

Biasanya hanya mengatur jenis tombol ke Custom works untuk saya, tetapi untuk alasan lain saya perlu subkelas UIButton dan mengatur jenis tombol kembali ke default (Sistem), sehingga berkedip muncul kembali.

Pengaturan UIView.setAnimationsEnabled(false)sebelum mengubah judul dan kemudian menjadi benar lagi setelah itu tidak menghindari kedip untuk saya, tidak peduli apakah saya menelepon self.layoutIfNeeded()atau tidak.

Ini, dan hanya ini dalam urutan yang tepat berikut, bekerja untuk saya dengan iOS 9 dan 10 beta:

1) Buat subkelas untuk UIButton (jangan lupa mengatur kelas khusus untuk tombol di Storyboard juga).

2) Ganti setTitle:forState:sebagai berikut:

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

Di Interface Builder, Anda dapat membiarkan jenis tombol ke Sistem, tidak perlu mengubahnya ke Tipe Kustom agar pendekatan ini berfungsi.

Saya harap ini membantu orang lain, saya sudah berjuang begitu lama dengan tombol-tombol berkedip yang menjengkelkan yang saya harap dapat menghindarinya kepada orang lain;)

cdf1982
sumber
Jangan lupa layoutIfNeeded():]
Tai Le
6

Anda cukup membuat tombol Kustom dan itu akan berhenti bernyawa saat mengubah judul.

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

Anda juga dapat melakukannya di kotak centang Storyboard: pilih tombol di storyboard -> pilih inspektur atribut (keempat dari sisi kiri) -> di menu drop-down 'Type', pilih 'Custom', bukan 'System' yang mungkin dipilih .

Semoga berhasil!

Mendy
sumber
3

Anda dapat menghapus animasi dari lapisan label judul:

    [[[theButton titleLabel] layer] removeAllAnimations];
Jacksonh
sumber
Saya memeriksa semua jawaban. Yang ini adalah yang terbaik.
Rudolf Adamkovič
2
Itu masih berkedip tapi lebih baik.
Lucien
INI HARUS MENJAWAB JAWABANNYA.
mxcl
3

Xhacker Liu versi 4 dari Swift menjawab

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 
faraz khonsari
sumber
1

UIButton dengan systemtipe memiliki animasi implisit aktif setTitle(_:for:). Anda dapat memperbaikinya dengan dua cara berbeda:

  1. Setel jenis tombol ke custom, baik dari kode atau Pembuat Antarmuka:
let button = UIButton(type: .custom)

masukkan deskripsi gambar di sini

  1. Nonaktifkan animasi dari kode:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}
sgl0v
sumber
0

Saya telah menemukan bahwa solusi ini bekerja dengan UIButtonTypeSystem juga tetapi hanya akan berfungsi jika tombol diaktifkan karena beberapa alasan.

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

Jadi, Anda harus menambahkan ini jika Anda perlu tombol untuk dinonaktifkan saat mengatur judulnya.

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

(iOS 7, Xcode 5)

sCha
sumber
Hanya mengonfirmasi bahwa solusi ini tidak lagi berfungsi di iOS 7.1.
sCha
jangan kira Anda sudah menemukan solusi untuk 7.1?
George Green
@GeorgeGreen tidak dapat menemukan solusi yang berfungsi untuk UIButtonTypeSystem . Saya harus menggunakan UIButtonTypeCustom .
sCha
Sejak 7.1, Anda harus menerapkan perubahan judul ke semua negara, mengaturnya hanya untuk keadaan normal tidak lagi berlaku. [_button setTitle:@"title" forState:UIControlStateDisabled]
Sam
0

Menggabungkan jawaban-jawaban hebat di atas menghasilkan pemecahan masalah berikut untuk 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];
}
AppsolutEinfach
sumber
0

Saya mendapat masalah animasi yang jelek ketika mengubah judul tombol di pengontrol tampilan dalam UITabBarController. Judul-judul yang awalnya diatur dalam storyboard muncul sebentar sebelum menghilang ke nilai-nilai baru mereka.

Saya ingin mengulangi semua subview dan menggunakan judul tombol sebagai kunci untuk mendapatkan nilai yang dilokalkan dengan NSLocalizedString, seperti;

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

}

Saya menemukan bahwa apa yang memicu animasi sebenarnya adalah panggilan ke btn.titleLabel.text. Jadi untuk tetap menggunakan storyboard dan memiliki komponen yang dilokalisasi secara dinamis seperti ini, saya pastikan untuk mengatur ID Restorasi setiap tombol (di Identity Inspector) sama dengan judul dan menggunakannya sebagai kunci alih-alih judul;

for(UIView *v in view.subviews) {

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

}

Tidak ideal, tetapi bekerja ..

Michael
sumber
0

Anda benar-benar dapat mengatur judul di luar blok animasi, pastikan untuk memanggil layoutIfNeeded()di dalam 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()
}

Jika Anda memiliki banyak tombol, pertimbangkan untuk memanggil layoutIfNeeded()tampilan super:

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

Ekstensi Xhacker Liu dikonversi ke Swift 3:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}
Paweł
sumber
-1

Mungkin menghasilkan 2 animasi dan 2 tombol adalah solusi yang lebih baik, untuk menghindari masalah yang muncul dengan menghidupkan dan mengubah teks tombol?

Saya membuat uibutton kedua dan menghasilkan 2 animasi, solusi ini berfungsi tanpa hickup.

    _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;}];
coda
sumber
-1

Saya membuatnya bekerja dengan kombinasi jawaban:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];
Jasper
sumber
-1

Perpanjangan yang nyaman untuk perubahan judul tombol animasi di Swift yang berfungsi baik dengan implementasi default:

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)
    }
  }
}
Richard Topchii
sumber
@Fogmeister 1. Jawaban saya berbeda 2. Sintaks Swift terbaru. Konsisten dengan API Apple untuk UIButton.
Richard Topchii