Làm thế nào để ngăn chặn hoạt hình UIButton không mong muốn khi thay đổi tiêu đề?


211

Trong iOS 7, các tiêu đề UIButton của tôi hoạt hình vào và ra không đúng lúc - muộn. Vấn đề này không xuất hiện trên iOS 6. Tôi chỉ đang sử dụng:

[self setTitle:text forState:UIControlStateNormal];

Tôi muốn điều này xảy ra ngay lập tức và không có khung trống. Nháy mắt này đặc biệt gây mất tập trung và thu hút sự chú ý từ các hình ảnh động khác.


Chúng tôi cũng đang trải nghiệm điều này. Không chắc đó là lỗi iOS7 hay thứ gì đó chúng ta nên sửa.
Sway

Hãy thử, [self.button setHighlighted: NO];
karthika

Cảm ơn những ý tưởng này. Tôi đã thử setHighlighted: KHÔNG, nhưng không có may mắn ở đó. Tôi có thể giảm nháy mắt bằng cách đặt setTitle bên trong: [UIView animateWithDuration: 0.0f animations: ^ {...}];
exsulto

1
Bạn có thể sử dụng cách giải quyết này trong một số trường hợp : self.button.titleLabel.text = text. Nhưng điều này không thay đổi kích thước khung nhãn và không hoạt động chính xác với UIControlStates
zxcat

Đó là một cách giải quyết thông minh. Tôi sẽ chơi với điều này và xem điều gì xảy ra, thật không may, tôi đang sử dụng UIControlStates.
exsulto

Câu trả lời:


165

Điều này hoạt động cho các nút tùy chỉnh:

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

Đối với các nút hệ thống, bạn cần thêm nút này trước khi bật lại hình động (cảm ơn bạn @Klaas):

[_button layoutIfNeeded];

12
Thật không may, điều này dường như không hoạt động. Không thực hiệnWithoutAnimation
Sway

9
Ok, vì vậy, cách khắc phục cuối cùng là để trống văn bản UIButton ban đầu để khi tôi đặt mã bằng mã, nó không kích hoạt hoạt ảnh.
Sway

27
Điều này chỉ hoạt động nếu bạn đặt loại nút thành tùy chỉnh, theo câu trả lời này stackoverflow.com/a/20718467/62 .
Liron Yahdav

15
Kể từ iOS 7.1, tôi đã phải thêm[_button layoutIfNeeded];
Klaas

6
@LironYahdav nếu bạn có loại nút được đặt thành UIButtonTypeCustom, thì câu trả lời này là không bắt buộc.
DonnaLea

262

Sử dụng performWithoutAnimation:phương pháp và sau đó buộc bố trí xảy ra ngay lập tức thay vì sau này.

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

11
Câu trả lời này hoạt động cũng như câu trả lời được chấp nhận, nhưng có vẻ đẹp hơn vì được gói gọn hơn - không thể quên thêm [UIView setAnimationsEnables: YES] hoặc để xóa nó đi.
siburb

19
Nó hoạt động cho các nút hệ thống nếu bạn gọi [button layoutIfNeeded];bên trong khối.
Alexandre Blin

1
BTW, đối với các nút hệ thống, bố trí IfNeed nên được gọi sau khi văn bản thay đổi
Yon

Đây là giải pháp tốt nhất! Chúc mừng
sachadso

Đây là một trong những chính xác cho tôi. Nó được bình chọn nhiều nhất và ở vị trí thứ 6.
Hay đấy

79

Thay đổi loại nút để xây dựng giao diện biểu mẫu tùy chỉnh.

nhập mô tả hình ảnh ở đây

Điều này làm việc cho tôi.


6
Giải pháp tốt nhất! Cảm ơn bạn.
Thomás Calmon

3
Nhưng điều này cũng vô hiệu hóa hình ảnh động trên nút bấm. Tôi chỉ muốn tắt hình ảnh động trên nút hiển thị.
Piotr Wasilewicz

Điều này hoạt động nếu bạn không quan tâm đến hình ảnh động khi nhấn nút.
Joaquin Pereira

Tôi đã có một vài nút được đặt như thế này và rõ ràng đây là câu trả lời tao nhã nhất cho trường hợp của tôi. Rất vui, cảm ơn!
Zoltán

79

Trong Swift bạn có thể sử dụng:

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

1
Đây là phương pháp dễ nhất. Và cảm ơn bạn đã bao gồm một câu trả lời nhanh chóng btw
đơn giản

1
Câu trả lời hay nhất cho Swift!
Nubaslon

Có một lỗi khó chịu khi thay đổi tiêu đề UIButton trong khi ngoài màn hình sẽ gây ra thời gian hoạt hình kỳ lạ với InteractivePopGestureRecognizer và điều này đã giải quyết nó. Tôi vẫn nghĩ rằng đó là một lỗi với HĐH
SparkyRobinson

Điều kỳ lạ là .layout IfNeeded () phải được gọi, nhưng tôi đã thử nghiệm cả hai cách trong Swift 5 và nó chắc chắn vẫn hoạt hình mà không có nó.
mèo hoang12

2
Không hẳn vậy. Nếu bạn không gọi layoutIfNeeded()thì nút được gắn cờ là cần được vẽ lại nhưng điều này sẽ không xảy ra cho đến khi bố trí tiếp theo vượt qua, sẽ nằm ngoàiperformWithoutAnimation
Paulw11

60

Xin lưu ý :

khi " buttonType " của _button là "UIButtonTypeSystem" , bên dưới đang không hợp lệ :

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

khi " buttonType " của _button là "UIButtonTypeCustom" , mã ở trên là hợp lệ .


Không thể tin được tôi đã dành bao nhiêu thời gian trước khi nhận ra bạn chỉ cần thay đổi loại nút ... ugh ...
Sandy Chapman

Hoạt động mà không cần bất kỳ mã. Chỉ thay đổi loại nút và nó sẽ hoạt động.
Alex Motor

52

Bắt đầu trong iOS 7.1, giải pháp duy nhất hiệu quả với tôi là khởi tạo nút bằng loại UIButtonTypeCustom.


Đây là cách tiếp cận hợp lý nhất cho bất kỳ ai không yêu cầu UIButtonTypeSystem.
DonnaLea

Điều này đã kết thúc hoạt động tốt nhất đối với tôi, tôi chỉ cần tạo một nút TÙY CHỈNH và làm cho nó trông và nổi bật như một nút hệ thống. Khó có thể thấy sự khác biệt nhưng bạn không có sự chậm trễ đó.
Travis M.

18

Vì vậy, tôi tìm giải pháp làm việc:

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

Đầu tiên, chúng tôi thay đổi tiêu đề cho nút, sau đó thay đổi kích thước nút cho tiêu đề này


1
Tôi sử dụng cùng một cách giải quyết. Câu trả lời được chấp nhận không làm việc cho tôi.
deej

Điều này khiến tiêu đề nhấp nháy hai lần, ít nhất là với iOS 8.
Jordan H

1
Điều này làm việc cho tôi trong cả 7.1 và 8.1 mà không cần flash. Đơn giản và hiệu quả.
Todd

Hoạt động hoàn hảo trong iOS 11, mặc dù tôi phải sử dụng lại cùng một chuỗi cho dòng thứ hai (sử dụng tiêu đề của nhãn nút khiến nó nhấp nháy).
SilverWolf - Phục hồi Monica

13

Đặt loại nút thành UIButtonTypeCustom và nó sẽ dừng nhấp nháy


Làm thế nào tất cả những "giải pháp" giải pháp đó có thể có rất nhiều sự ủng hộ khi câu trả lời đơn giản này phải giải quyết vấn đề này 99% thời gian ...
Rob

12

Swift 5

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

Không biết tại sao điều này hoạt động nhưng nó làm và đó là giải pháp sạch nhất. UIKit thật kỳ lạ.
Nathan Hosselton

11

Tôi đã tạo một tiện ích mở rộng Swift để làm điều này:

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

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

Hoạt động với tôi trên iOS 8 và 9, với UIButtonTypeSystem .

(Mã dành cho Swift 2, Swift 3 và Objective-C phải giống nhau)


Không sử dụng nó bây giờ nhưng rất tiện để có xung quanh!
Francis Reynold

9

Đặt loại UIButton là Tùy chỉnh. Điều đó sẽ loại bỏ mờ dần trong và ngoài hình ảnh động.


1
Điều này nên có nhiều upvote! Hoạt động hoàn hảo và vô hiệu hóa hình ảnh động ở nguyên nhân gốc, thay vì các cách giải quyết khác.
Jesper Schläger

7

Thông thường chỉ cần đặt loại nút thành Tùy chỉnh hoạt động cho tôi, nhưng vì lý do khác, tôi cần phải phân lớp UIButton và đặt loại nút trở về mặc định (Hệ thống), do đó, nhấp nháy xuất hiện lại.

Đặt UIView.setAnimationsEnabled(false)trước khi thay đổi tiêu đề và sau đó trở lại thành đúng sau đó không tránh được nháy mắt cho tôi, bất kể tôi có gọi self.layoutIfNeeded()hay không.

Điều này và chỉ điều này theo thứ tự chính xác sau đây, đã hoạt động với tôi với iOS 9 và 10 beta:

1) Tạo một lớp con cho UIButton (đừng quên đặt lớp tùy chỉnh cho nút trong Bảng phân cảnh).

2) Ghi đè setTitle:forState:như sau:

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

Trong Trình tạo giao diện, bạn có thể để loại nút thành Hệ thống, không cần thay đổi thành Loại tùy chỉnh để phương pháp này hoạt động.

Tôi hy vọng điều này sẽ giúp được người khác, tôi đã vật lộn quá lâu với các nút nhấp nháy khó chịu mà tôi hy vọng sẽ tránh được cho người khác;)


Đừng quên layoutIfNeeded():]
Tai Le

6

Bạn có thể chỉ cần tạo nút Tùy chỉnh và nó sẽ dừng hoạt hình trong khi thay đổi tiêu đề.

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

bạn cũng có thể làm điều đó trong hộp kiểm Storyboard: chọn nút trong bảng phân cảnh -> chọn trình kiểm tra thuộc tính (thứ tư từ bên trái) -> trong menu thả xuống 'Loại', chọn 'Tùy chỉnh' thay vì 'Hệ thống' có thể đã được chọn .

Chúc may mắn!


3

Bạn có thể xóa hình động từ lớp nhãn của tiêu đề:

    [[[theButton titleLabel] layer] removeAllAnimations];

Tôi đã đi qua tất cả các câu trả lời. Điều này là tốt nhất.
Rudolf Adamkovič

2
Nó vẫn nhấp nháy nhưng tốt hơn.
Lucien

NÀY NÊN TRẢ LỜI.
mxcl

3

Phiên bản Swift 4 của Xhacker Liu trả lời

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 

1

UIButton với systemloại có hình ảnh động ngầm setTitle(_:for:). Bạn có thể sửa nó theo hai cách khác nhau:

  1. Đặt loại nút thành custom, từ mã hoặc Trình tạo giao diện:
let button = UIButton(type: .custom)

nhập mô tả hình ảnh ở đây

  1. Vô hiệu hóa hình ảnh động từ mã:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}

0

Tôi đã thấy rằng cách giải quyết này cũng hoạt động với UIButtonTypeSystem nhưng sẽ chỉ hoạt động nếu nút được bật vì một số lý do.

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

Vì vậy, bạn sẽ phải thêm những thứ này nếu bạn cần tắt nút khi đặt tiêu đề.

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

(iOS 7, Xcode 5)


Chỉ cần xác nhận rằng cách giải quyết này không còn hoạt động trên iOS 7.1.
sCha

đừng cho rằng bạn đã tìm thấy giải pháp cho 7.1?
George Green

@GeorgeGreen không thể tìm thấy bất kỳ giải pháp hoạt động nào cho UIButtonTypeSystem . Tôi đã phải sử dụng UIButtonTypeCustom .
sCha

Kể từ 7.1, bạn sẽ cần áp dụng thay đổi tiêu đề cho tất cả các trạng thái, chỉ đặt nó ở trạng thái bình thường không còn áp dụng. [_button setTitle:@"title" forState:UIControlStateDisabled]
Sam

0

Kết hợp các câu trả lời tuyệt vời ở trên dẫn đến cách giải quyết sau cho 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

Tôi gặp vấn đề về hoạt hình xấu khi thay đổi tiêu đề nút trong bộ điều khiển xem trong UITabBarCont kiểm. Các tiêu đề ban đầu được đặt trong bảng phân cảnh đã xuất hiện trong một thời gian ngắn trước khi mờ dần vào các giá trị mới của chúng.

Tôi muốn lặp lại qua tất cả các cuộc phỏng vấn và sử dụng các tiêu đề nút làm khóa để nhận các giá trị được bản địa hóa của chúng với NSLocalizedString, chẳng hạn như;

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

}

Tôi phát hiện ra rằng những gì kích hoạt hoạt hình thực sự là cuộc gọi đến btn.titleLabel.text. Vì vậy, để vẫn sử dụng bảng phân cảnh và để các thành phần được định vị động như thế này, tôi đảm bảo đặt ID khôi phục của mỗi nút (trong Trình kiểm tra danh tính) giống như tiêu đề và sử dụng làm khóa thay vì tiêu đề;

for(UIView *v in view.subviews) {

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

}

Không lý tưởng, nhưng hoạt động ..


0

Bạn thực sự có thể đặt tiêu đề bên ngoài khối hoạt hình, chỉ cần đảm bảo gọi layoutIfNeeded()bên trong biểu diễnWithoutAnimation:

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

Nếu bạn có một loạt các nút, hãy xem xét chỉ gọi layoutIfNeeded()trên chế độ xem siêu:

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

0

Tiện ích mở rộng Xhacker Liu được chuyển đổi thành Swift 3:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

-1

Có lẽ tạo 2 hình động và 2 nút là một giải pháp tốt hơn, để tránh sự cố xuất hiện với hoạt ảnh và thay đổi văn bản của nút?

Tôi đã tạo một uibutton thứ hai và tạo ra 2 hình ảnh động, giải pháp này hoạt động mà không có sự thay đổi.

    _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

Tôi đã làm cho nó hoạt động với sự kết hợp của các câu trả lời:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];

-1

Một tiện ích mở rộng thuận tiện cho thay đổi tiêu đề nút hoạt hình trong Swift, hoạt động độc đáo với cách triển khai mặc định:

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. Câu trả lời của tôi khác 2. Cú pháp Swift cập nhật 3. Phù hợp với API của Apple cho UIButton.
Richard Topchii
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.