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.


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

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

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.


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

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 .


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.


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


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


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)

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)


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.


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;)


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!


3

Anda dapat menghapus animasi dari lapisan label judul:

    [[[theButton titleLabel] layer] removeAllAnimations];

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

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

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)


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

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 ..


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

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

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

-1

Saya membuatnya bekerja dengan kombinasi jawaban:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];

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

@Fogmeister 1. Jawaban saya berbeda 2. Sintaks Swift terbaru. Konsisten dengan API Apple untuk UIButton.
Richard Topchii
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.