วิธีป้องกัน UIButton ไม่ให้กะพริบเมื่ออัปเดตชื่อ


85

เมื่อฉันเรียก setTitle บน UIButton ปุ่มจะกะพริบใน iOS 7 ฉันลองตั้งค่า myButton.highlighted = NO แต่นั่นไม่ได้หยุดปุ่มไม่ให้กระพริบ

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

myButton.highlighted = NO;

นี่คือวิธีตั้งค่าตัวจับเวลาที่อัปเดตชื่อ:

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

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

นี่คือวิธีการอัปเดตชื่อเรื่อง:

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

ไม่ควรกระพริบ คุณกำลังพยายามทำสิ่งนี้กับเธรดพื้นหลังหรือไม่?
BergQuester

ใช่มันถูกตั้งเวลาเพื่ออัปเดตชื่อปุ่มทุก ๆ วินาที (ซึ่งฉันคิดว่าสร้างเธรดของตัวเอง)
FierceMonkey

ตัวจับเวลาจะทำงานบนเธรดที่แยกจากกันเท่านั้นหากคุณตั้งค่าให้ทำเช่นนั้น เราจะดูวิธีการอัปเดตชื่อเรื่องและวิธีตั้งค่าตัวจับเวลาได้ไหม
BergQuester

ฉันเพิ่มรหัสที่ร้องขอในคำถามหลัก
FierceMonkey

คำตอบ:


208

ตั้งค่าประเภทปุ่มเป็นUIButtonTypeCustomแล้วมันจะหยุดกะพริบ


16
นี่ควรเป็นคำตอบที่ต้องการจริงๆ ทางออกที่ง่ายที่สุด และมันใช้งานได้จริง
Johan Karlsson

4
เห็นด้วย ฉันลองวิธีแก้ปัญหาอื่น ๆ มากมายและนี่คือสิ่งที่ทำได้ด้วยตัวเองทั้งหมด
BBQ Steve

2
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ทางออกที่ง่ายที่สุดจนถึงตอนนี้
Machado

1
ใช้งานได้เหมือนมีเสน่ห์! ขอบคุณ

2
ฉันคิดว่านี่เป็นทางออกที่ดีจริงๆโดยไม่ต้องเขียนโค้ดใด ๆ
Chauyan

58

แนวทางที่ดีกว่า[UIView setAnimationsEnabled:NO]ที่อาจส่งผลกระทบต่อภาพเคลื่อนไหวอื่น ๆ คือปิดการใช้งานเฉพาะภาพเคลื่อนไหวชื่อเรื่องเท่านั้น

วัตถุประสงค์ -C:

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

รวดเร็ว:

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

เพิ่งลองใช้โซลูชัน Swift บน iOS ล่าสุด - ใช้งานได้ดี
Ronen Rabinovici

1
ผู้กอบกู้วัน ไชโย!
pkc456

เพิ่งลองใช้ใน Swift 3 และใช้งานได้โดยไม่ต้องใช้ layoutIfNeeded ()
user1898712

3
นี่ควรเป็นคำตอบที่ได้รับการยอมรับโดยไม่ต้องสงสัย!
Julius

1
นี่เป็นวิธีที่ดีที่สุดในการทำเช่นนี้ ตอบโจทย์มาก!
aecend

29

* โปรดทราบ *

เมื่อ " buttonType " ของ _button เป็น"UIButtonTypeSystem"รหัสด้านล่างไม่ถูกต้อง

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

เมื่อ " buttonType " ของ _button เป็น"UIButtonTypeCustom"เหนือรหัสที่ถูกต้อง


19

ดูคำตอบจากHow to stop UIButton animation ที่ไม่ต้องการเมื่อเปลี่ยนชื่อเรื่อง? :

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

7
@FierceMonkey ลองเพิ่มการเรียกร้องให้:layoutIfNeeded [elapsed layoutIfNeeded];สิ่งนี้ลบการกะพริบในกรณีของฉัน
Klaas

1
layoutIfNeeded ทำเพื่อฉัน
Kaolin Fire

ดูเหมือนว่าจะเป็นวิธีแก้ปัญหาที่ค่อนข้างสกปรก แต่layoutIfNeededดูเหมือนจะใช้งานได้
PrzemysławWrzesiński

7

คุณสามารถสร้างฟังก์ชันอื่นสำหรับ UIButton เพื่อการใช้งานในอนาคตได้อย่างง่ายดาย

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

นั่นแหละ!

และตั้งชื่อเรื่องตามที่คุณเคยทำมาก่อน แต่แทนที่setTitleด้วยsetTitleWithoutAnimation


6

พฤติกรรม"setTitle"เริ่มต้นคือความเกลียดชังอย่างแน่นอน!

ทางออกของฉันคือ:

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

นอกจากนี้ในกระดานเรื่องราวภายใต้คุณสมบัติของปุ่มฉันยกเลิกการเลือก:

  • กลับด้านบนไฮไลต์
  • ไฮไลต์ปรับภาพ

และตรวจสอบ:

  • ปิดใช้งานปรับภาพ

ทดสอบและทำงานบนiOS 8ด้วย

อัปเดต - Swift

ฉันขอแนะนำให้คุณสร้างปุ่มที่กำหนดเองและแทนที่เมธอด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)
    }

}

ฉันลองใช้วิธีนี้ (คลาสย่อยแทนที่ setTitle: forState: และปิดการใช้งาน - เปิดใช้งาน UIView.setAnimationsEnabled) ไม่ทำงานสำหรับฉันใน iOS 9 และ 10 เบต้า ใช้งานได้ถ้าฉันปิดการใช้งานภาพเคลื่อนไหวเท่านั้น แต่มันจะหายไปสำหรับทุก UIView ...
cdf1982

2

ลองใช้วิธีนี้ใช้ได้กับ IOS เวอร์ชันใหม่กว่า:

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

}

0

ฉันยังใหม่กับการเขียนโค้ดและ Stackoverflow ดังนั้นจึงไม่มีชื่อเสียงมากพอที่จะแสดงความคิดเห็นโดยตรงเพื่อขยายhttps://stackoverflow.com/users/4673064/daniel-tsengคำตอบที่ยอดเยี่ยม ดังนั้นฉันต้องเขียนคำตอบใหม่ของตัวเองและนี่คือ:

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

ใช้งานได้ดียกเว้น:

หากการโทรทั้งหมดของฉันในภายหลังในโค้ดถึง "setTitleWithoutAnimation" ไม่ได้ระบุผู้ส่งฉันจะได้รับข้อความแปลก ๆ เหล่านี้ที่เกี่ยวข้องกับ CoreMedia หรือ CoreData เช่น "ไม่สามารถสืบทอดสิทธิ์ CoreMedia จาก 2526: (null)"

นี่อาจเป็นพื้นฐานสำหรับการเข้ารหัสและ iOS แต่สำหรับฉันในฐานะผู้เขียนโค้ดตัวใหม่มันส่งฉันไปบนเส้นทางกระต่ายมาระยะหนึ่งเช่น: ส่วนขยายวันนี้ไม่สามารถสืบทอดสิทธิ์ CoreMedia จากที่ซึ่งผู้คนมีคำตอบที่น่าสนใจ แต่ไม่ ถึงต้นตอของปัญหาของฉัน

ในที่สุดฉันก็พบว่าฉันต้องทำตามและให้พารามิเตอร์ฟังก์ชันที่ไม่มีพารามิเตอร์ของฉันกล่าวคือฉันต้องระบุผู้ส่ง ผู้ส่งรายนั้นอาจเป็น UIButton, Any หรือ AnyObject ทั้งหมดนี้ใช้ได้ผล แต่ท้ายที่สุดแล้วดูเหมือนจะมีความขัดแย้งระหว่างการเพิ่มส่วนขยายของปุ่มด้วย "self" และไม่ได้บอกเป็นพิเศษในภายหลังว่าปุ่มกำลังใช้งานปุ่มนี้

อีกครั้งอาจจะธรรมดา แต่ยังใหม่สำหรับฉันดังนั้นฉันคิดว่ามันควรค่าแก่การแบ่งปัน


0

เคล็ดลับอีกประการหนึ่ง

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

วิธีนี้ใช้ได้เฉพาะเมื่อคุณทราบค่าของชื่อโดยไม่ต้องเรียก API ใด ๆ ชื่อของปุ่มจะถูกตั้งค่าก่อนที่จะโหลดมุมมองดังนั้นคุณจะไม่เห็นภาพเคลื่อนไหว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.