Cách ngăn UIButton nhấp nháy khi cập nhật tiêu đề


85

Khi tôi gọi setTitle trên UIButton, nút sẽ nhấp nháy trong iOS 7. Tôi đã thử đặt myButton.highlighted = NO, nhưng điều đó không ngăn được nút nhấp nháy.

[myButton setTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"elapsedLabelKey"] forState:UIControlStateNormal];

myButton.highlighted = NO;

Đây là cách tôi thiết lập bộ đếm thời gian cập nhật tiêu đề:

- (void)actionTimer {
    if (myTimer == nil) {

        myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0
                        target: self
                        selector: @selector(showActivity)
                        userInfo: nil
                        repeats: YES];
    }
}

Đây là phương pháp thực sự cập nhật các tiêu đề:

- (void)showActivity {

    NSString *sym = [[NSLocale currentLocale] objectForKey:NSLocaleCurrencySymbol];

    if (pauseInterval == nil) {

        // Update clock
        seconds = [[NSDate date] timeIntervalSinceDate:startInterval] - breakTime;

        // Update total earned
        secRate = rate.value / 60 / 60;
        total = secRate * seconds;
        [totalLabel setTitle:[NSString stringWithFormat:@"%@%.4f",sym,total] forState:UIControlStateNormal];

        days = seconds / (60 * 60 * 24);
        seconds -= days * (60 * 60 * 24);
        int hours = seconds / (60 * 60);
        fhours = (float)seconds / (60.0 * 60.0);
        seconds -= hours * (60 * 60);
        int minutes = seconds / 60;
        seconds -= minutes * 60;

        // Update the timer clock
        [elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
    }
}

Nó không được nhấp nháy. Bạn đang cố gắng làm điều này trên một chuỗi nền?
BergQuester

Có nó đang được đặt trong một bộ đếm thời gian để cập nhật tiêu đề nút mỗi giây (mà tôi nghĩ rằng tạo thread riêng của mình)
FierceMonkey

Bộ hẹn giờ chỉ chạy trên một chuỗi riêng biệt nếu bạn thiết lập chúng để làm như vậy. Chúng tôi có thể thấy phương pháp mà tiêu đề được cập nhật và cách bạn thiết lập bộ đếm thời gian không?
BergQuester

Tôi đã thêm mã yêu cầu cho câu hỏi chính
FierceMonkey

Câu trả lời:


205

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


16
Đây thực sự nên là câu trả lời ưa thích. Giải pháp đơn giản nhất. Và nó đang hoạt động.
Johan Karlsson

4
Đã đồng ý. Tôi đã thử rất nhiều giải pháp khác và đây là điều đã làm được, tất cả đều tự nó.
BBQ Steve

2
Đây phải là câu trả lời được chấp nhận. Giải pháp đơn giản nhất cho đến nay.
Machado

1
Hoạt động như một sự quyến rũ! Cảm ơn

2
Tôi nghĩ rằng đây là một giải pháp thực sự tốt mà không cần viết bất kỳ mã nào cho điều đó.
Chauyan

55

Một cách tiếp cận tốt hơn [UIView setAnimationsEnabled:NO]có thể ảnh hưởng đến các hoạt ảnh khác là chỉ tắt hoạt ảnh tiêu đề cụ thể.

Mục tiêu-C:

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

Nhanh:

UIView.performWithoutAnimation { 
    myButton.setTitle(text, for: .normal)
    myButton.layoutIfNeeded()
}

Vừa mới thử giải pháp Swift trên iOS mới nhất - hoạt động rất tốt.
Ronen Rabinovici

1
Vị cứu tinh ban ngày. Chúc mừng!
pkc456

Chỉ cần cố gắng này trong Swift 3, và nó hoạt động mà không cần dùng layoutIfNeeded ()
user1898712

3
Đây sẽ là câu trả lời được chấp nhận mà không nghi ngờ gì nữa!
Julius

1
Đây là cách tốt nhất để làm điều này. Câu trả lời chính xác!
'19

29

* Xin lưu ý *

khi " buttonType " của _button là "UIButtonTypeSystem" , mã bên dưới 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ệ .


19

Xem câu trả lời từ Cách dừng hoạt ảnh UIButton không mong muốn khi thay đổi tiêu đề? :

[UIView setAnimationsEnabled:NO];
[elapsed setTitle:[NSString stringWithFormat:@"%.2i:%.2i:%.2i:%.2i",days,hours,minutes,seconds] forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

7
@FierceMonkey thử thêm một cuộc gọi đến layoutIfNeeded: [elapsed layoutIfNeeded];. Điều này đã loại bỏ nhấp nháy trong trường hợp của tôi.
Klaas

1
layoutIfNeeded đã làm điều đó cho tôi.
Kaolin Fire

Nó có vẻ là một cách giải quyết khá bẩn, tuy nhiên layoutIfNeededsẽ xuất hiện để được làm việc
Przemysław Wrzesinski

7

Bạn chỉ có thể tạo một chức năng khác cho UIButton để dễ dàng sử dụng trong tương lai.

extension UIButton {
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
        UIView.performWithoutAnimation {
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        }
    }
}

Đó là nó!

Và chỉ cần đặt tiêu đề như trước đây nhưng thay thế setTitlebằngsetTitleWithoutAnimation


6

Hành vi "setTitle" mặc định chắc chắn là đáng ghét!

Giải pháp của tôi là:

[UIView setAnimationsEnabled:NO];
[_button layoutIfNeeded]; 
[_button setTitle:[NSString stringWithFormat:@"what" forState:UIControlStateNormal];
[UIView setAnimationsEnabled:YES];

Ngoài ra, trong bảng phân cảnh, dưới thuộc tính của nút, tôi đã bỏ chọn:

  • Đảo ngược khi được đánh dấu
  • Hình ảnh điều chỉnh được đánh dấu

Và kiểm tra:

  • Đã tắt điều chỉnh hình ảnh

Đã thử nghiệm và hoạt động trên iOS 8 .

Cập nhật - Swift

Tôi khuyên bạn nên tạo nút tùy chỉnh của mình và ghi đè phương thức setTitle .

class UnflashingButton: UIButton {
   
    override func setTitle(title: String?, forState state: UIControlState) {
        UIView.setAnimationsEnabled(false)
        self.layoutIfNeeded()
        super.setTitle(title, forState: state)
        UIView.setAnimationsEnabled(true)
    }

}

Tôi đã thử cách tiếp cận này (phân lớp, ghi đè setTitle: forState: và tắt bật UIView.setAnimationsEnabled). Không hoạt động đối với tôi trong iOS 9 và 10 beta. Nó hoạt động nếu tôi chỉ vô hiệu hóa hình ảnh động, nhưng sau đó họ đang bị mất cho mỗi UIView ...
cdf1982

2

Hãy thử điều này, điều này hoạt động trong các phiên bản IOS mới hơn:

class CustomButtonWithNoEffect : UIButton {
    override func setTitle(_ title: String?, for state: UIControlState) {
        UIView.performWithoutAnimation {
            super.setTitle(title, for: state)
            super.layoutIfNeeded()
        }
    }

}

0

Tôi mới sử dụng mã hóa và Stackoverflow, vì vậy không có đủ danh tiếng để nhận xét trực tiếp để mở rộng về câu trả lời xuất sắc https://stackoverflow.com/users/4673064/daniel-tseng . Vì vậy, tôi phải viết câu trả lời mới của riêng mình, và nó là:

extension UIButton {
    func setTitleWithoutAnimation(_ title: String?, for controlState: UIControlState) {
        UIView.performWithoutAnimation {
            self.setTitle(title, for: controlState)
            self.layoutIfNeeded()
        }
    }
}

Hoạt động tốt, NGOẠI TRỪ:

Nếu tất cả các cuộc gọi của tôi sau này trong mã tới "setTitleWithoutAnimation" không chỉ định người gửi, thì tôi nhận được những thông báo kỳ lạ này liên quan đến CoreMedia hoặc CoreData, ví dụ: "Không thể kế thừa quyền CoreMedia từ 2526: (null)"

Điều này có lẽ là khá cơ bản đối với mã hóa và iOS, nhưng đối với tôi là một lập trình viên mới, nó đã khiến tôi đi vào con đường mòn trong một thời gian, như trong: Today Extension Không thể kế thừa các quyền CoreMedia từ , nơi mọi người đã có câu trả lời thú vị nhưng điều đó KHÔNG đạt được gốc rễ của vấn đề của tôi.

Vì vậy, cuối cùng tôi thấy rằng tôi phải đi qua và cung cấp các tham số hàm ít tham số của mình, tức là tôi phải chỉ định một người gửi. Người gửi đó có thể là UIButton, Any hoặc AnyObject. Tất cả những điều đó đều hoạt động, nhưng cuối cùng dường như có mâu thuẫn giữa việc thêm tiện ích mở rộng nút với "self" và không nói cụ thể sau này rằng một nút đang sử dụng nó.

Một lần nữa, có lẽ là cơ bản, nhưng mới đối với tôi, vì vậy tôi nghĩ rằng nó sẽ đáng được chia sẻ.


0

Một thủ thuật khác

@IBOutlet private weak var button: UIButton! {
    didSet {
        button.setTitle(title, for: .normal)
    }
}

Điều này chỉ hoạt động nếu bạn biết giá trị của tiêu đề mà không thực hiện bất kỳ lệnh gọi API nào. Tiêu đề của nút sẽ được đặt trước khi chế độ xem được tải nên bạn sẽ không thấy hoạt ảnh

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.