จะหยุดการเคลื่อนไหวของ UIButton ที่ไม่ต้องการในการเปลี่ยนชื่อได้อย่างไร?


211

ใน iOS 7 ชื่อ UIButton ของฉันเคลื่อนไหวในและนอกเวลาผิด - สาย ปัญหานี้ไม่ปรากฏบน iOS 6 ฉันแค่ใช้:

[self setTitle:text forState:UIControlStateNormal];

ฉันต้องการสิ่งนี้เกิดขึ้นทันทีและไม่มีเฟรมว่างเปล่า การกะพริบนี้เบี่ยงเบนความสนใจเป็นพิเศษและดึงความสนใจออกไปจากภาพเคลื่อนไหวอื่น ๆ


เรากำลังประสบกับปัญหานี้เช่นกัน ไม่แน่ใจว่าเป็นบั๊ก iOS7 หรือบางอย่างที่เราควรแก้ไข
Sway

ลองใช้ [ตั้งค่าปุ่มตัวเองไฮไลต์: ไม่];
karthika

ขอบคุณสำหรับความคิดเหล่านี้ ฉันลองชุดไฮไลต์: ไม่ แต่ก็ไม่มีโชค ฉันสามารถลดการกะพริบได้โดยวาง setTitle ไว้ภายใน: [UIView animateWithDuration: 0.0f ภาพเคลื่อนไหว: ^ {... }];
exsulto

1
self.button.titleLabel.text = textคุณสามารถใช้วิธีแก้ปัญหานี้ในบางกรณี: แต่นี่จะไม่ปรับขนาดกรอบป้ายกำกับและไม่ทำงานกับ UIControlStates อย่างถูกต้อง
zxcat

นั่นเป็นวิธีแก้ปัญหาที่ฉลาด ฉันจะเล่นกับสิ่งนี้และดูว่าเกิดอะไรขึ้นโชคไม่ดีที่ฉันใช้ UIControlStates
exsulto

คำตอบ:


165

ใช้งานได้กับปุ่มที่กำหนดเอง:

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

สำหรับปุ่มระบบคุณต้องเพิ่มสิ่งนี้ก่อนที่จะเปิดใช้งานภาพเคลื่อนไหวอีกครั้ง (ขอบคุณ @Klaas):

[_button layoutIfNeeded];

12
น่าเสียดายที่นี่ไม่ได้ผล ไม่มีการดำเนินการโดยไม่ต้องแจ้ง
Sway

9
ตกลงดังนั้นการแก้ไขที่ทำงานในท้ายที่สุดคือการปล่อยให้ข้อความ UIButton ดั้งเดิมว่างเปล่าดังนั้นเมื่อฉันตั้งค่าด้วยรหัสมันจะไม่เรียกภาพเคลื่อนไหว
Sway

27
นี้จะทำงานเฉพาะถ้าคุณตั้งค่าชนิดปุ่มที่จะกำหนดเองตามคำตอบนี้stackoverflow.com/a/20718467/62
Liron Yahdav

15
ในฐานะของ iOS 7.1 ฉันต้องเพิ่ม[_button layoutIfNeeded];
Klaas

6
@LironYahdav หากคุณตั้งค่าชนิดปุ่มเป็น UIButtonTypeCustom ดังนั้นไม่จำเป็นต้องใช้คำตอบนี้
DonnaLea

262

ใช้performWithoutAnimation:วิธีการและบังคับให้เค้าโครงเกิดขึ้นทันทีแทนที่จะเป็นภายหลัง

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

11
วิธีนี้ใช้ได้ผลเช่นเดียวกับคำตอบที่ได้รับการยอมรับ แต่ดูเหมือนดีกว่าเพราะมันเป็นแบบห่อหุ้มมากขึ้น - เป็นไปไม่ได้ที่จะลืมเพิ่ม [UIView setAnimationsEnabled: YES] หรือเพื่อลบออกจากแทร็ก
siburb

19
มันใช้งานได้กับปุ่มระบบหากคุณโทร[button layoutIfNeeded];เข้าไปในบล็อก
Alexandre Blin

1
BTW, สำหรับปุ่มระบบ layoutIfNeed ควรจะเรียกว่าหลังจากการเปลี่ยนแปลงข้อความใน
Yon

นี่คือทางออกที่ดีที่สุด! ไชโย
sachadso

นี่คือสิ่งที่ถูกต้องสำหรับฉัน มันได้รับการโหวตมากที่สุดและอันดับที่ 6 ดี ...
solgar

79

เปลี่ยนประเภทปุ่มเป็นเครื่องมือสร้างอินเตอร์เฟสแบบกำหนดเอง

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งนี้ใช้ได้สำหรับฉัน


6
ทางออกที่ดีที่สุด! ขอบคุณ.
Thomás Calmon

3
แต่สิ่งนี้ยังปิดใช้งานภาพเคลื่อนไหวเมื่อคลิกปุ่ม ฉันต้องการปิดใช้งานภาพเคลื่อนไหวเมื่อปุ่มแสดงเท่านั้น
Piotr Wasilewicz

ใช้งานได้หากคุณไม่สนใจภาพเคลื่อนไหวเมื่อกดปุ่ม
Joaquin Pereira

ฉันมีปุ่มสองสามชุดแบบนี้และเห็นได้ชัดว่านี่เป็นคำตอบที่หรูหราที่สุดสำหรับเคสของฉัน ดีมากขอบคุณ!
Zoltán

79

ใน Swift คุณสามารถใช้:

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

1
นี่เป็นวิธีที่ง่ายที่สุด และขอขอบคุณสำหรับการรวมคำตอบอย่างรวดเร็ว btw
simplexity

1
คำตอบที่ดีที่สุดสำหรับ Swift!
นูบาสลอน

มีข้อผิดพลาดที่น่ารำคาญที่เปลี่ยนชื่อ UIButton ในขณะที่นอกจอจะทำให้การกำหนดเวลาภาพเคลื่อนไหวแปลก ๆ ด้วย interactivePopGestureRecognizer และสิ่งนี้แก้ไขได้ ฉันยังคิดว่ามันเป็นข้อผิดพลาดกับระบบปฏิบัติการแม้ว่า
SparkyRobinson

แปลกที่ต้องมีการเรียกใช้หากจำเป็นต้องมี () แต่ฉันทดสอบทั้งสองวิธีใน Swift 5 และแน่นอนว่ามันยังคงเคลื่อนไหวโดยไม่มี
wildcat12

2
ไม่ได้จริงๆ หากคุณไม่ได้โทรlayoutIfNeeded()แล้วปุ่มจะถูกตั้งค่าสถานะว่าจำเป็นต้องถูกวาดขึ้นใหม่ แต่สิ่งนี้จะไม่เกิดขึ้นจนกว่าจะผ่านเลย์เอาต์ถัดไปซึ่งจะอยู่ด้านนอกperformWithoutAnimation
Paulw11 11

60

โปรดทราบ:

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

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

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


ไม่อยากจะเชื่อเลยว่าฉันใช้เวลานานเท่าไหร่ในการหาว่าคุณแค่ต้องเปลี่ยนประเภทปุ่ม ... เอ่อ ...
Sandy Chapman

ทำงานได้โดยไม่ต้องใช้รหัสใด ๆ เปลี่ยนประเภทปุ่มเท่านั้นและจะใช้งานได้
Alex Motor

52

เริ่มต้นใน iOS 7.1 UIButtonTypeCustomโซลูชั่นเดียวที่ทำงานให้ฉันได้รับการเริ่มต้นปุ่มที่มีประเภท


นี่เป็นวิธีที่เหมาะสมที่สุดสำหรับทุกคนที่ไม่ต้องการ UIButtonTypeSystem
DonnaLea

สิ่งนี้จบลงได้ดีที่สุดสำหรับฉันฉันเพิ่งสร้างปุ่ม CUSTOM และทำให้มันดูและเน้นเหมือนปุ่มระบบ เห็นความแตกต่างได้ยาก แต่คุณไม่มีความล่าช้านั้น
Travis M.

18

ดังนั้นฉันหาวิธีแก้ปัญหาทำงาน:

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

ในตอนแรกเราเปลี่ยนหัวเรื่องสำหรับปุ่มจากนั้นปรับขนาดปุ่มสำหรับชื่อนี้


1
ฉันใช้วิธีแก้ปัญหาเดียวกัน คำตอบที่ยอมรับใช้ไม่ได้สำหรับฉัน
deej

สิ่งนี้ทำให้ชื่อเรื่องแฟลชสองครั้งเป็นอย่างน้อยกับ iOS 8
Jordan H

1
สิ่งนี้ใช้ได้กับฉันในทั้ง 7.1 และ 8.1 โดยไม่ต้องกะพริบ ง่ายและมีประสิทธิภาพ
ทอดด์

ทำงานได้อย่างสมบูรณ์แบบใน iOS 11 ถึงแม้ว่าฉันจะต้องใช้สตริงเดิมอีกครั้งสำหรับบรรทัดที่สอง (การใช้ชื่อป้ายกำกับของปุ่มทำให้มันกะพริบ)
SilverWolf - Reinstate Monica

13

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


วิธีแก้ปัญหา "วิธีแก้ปัญหา" เหล่านั้นทั้งหมดมี upvotes มากมายเมื่อคำตอบง่าย ๆ นี้ต้องแก้ปัญหานี้ 99% ของเวลา ...
Rob Rob

12

สวิฟท์ 5

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

ไม่รู้เลยว่าทำไมมันถึงใช้งานได้ แต่มันทำงานได้และมันเป็นคำตอบที่สะอาดที่สุด UIKit แปลก
Nathan Hosselton

11

ฉันได้ทำการขยายอย่างรวดเร็วเพื่อทำสิ่งนี้:

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

        setTitle(title, forState: .Normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

งานสำหรับฉันบน iOS 8 และ 9 UIButtonTypeSystemด้วย

(รหัสสำหรับ Swift 2, Swift 3 และ Objective-C ควรเหมือนกัน)


จะไม่ใช้มันตอนนี้ แต่มีประโยชน์มากที่จะมีอยู่รอบ ๆ !
ฟรานซิสเรย์โนลด์ส

9

ตั้งค่าชนิด UIButton เป็นกำหนดเอง ที่ควรลบภาพเคลื่อนไหวที่จางหายไปและออก


1
ควรมี upvotes มากกว่านี้! ทำงานอย่างสมบูรณ์แบบและปิดใช้งานภาพเคลื่อนไหวที่สาเหตุของปัญหาแทนที่จะเป็นการแก้ไขปัญหาอื่น ๆ
Jesper Schläger

7

โดยปกติแล้วการตั้งค่าประเภทปุ่มเป็นแบบกำหนดเองใช้งานได้สำหรับฉัน แต่ด้วยเหตุผลอื่นฉันต้องใช้คลาสย่อย UIButton และตั้งค่าประเภทปุ่มกลับเป็นค่าเริ่มต้น (ระบบ) ดังนั้นการกะพริบจึงปรากฏขึ้นอีกครั้ง

การตั้งค่าUIView.setAnimationsEnabled(false)ก่อนที่จะเปลี่ยนชื่อเรื่องและจากนั้นเป็นจริงอีกครั้งหลังจากนั้นก็ไม่ได้หลีกเลี่ยงการกะพริบสำหรับฉันไม่ว่าฉันจะโทรออกself.layoutIfNeeded()หรือไม่ก็ตาม

สิ่งนี้และเฉพาะสิ่งนี้ตามลำดับต่อไปนี้เท่านั้นที่ทำงานกับฉันด้วย iOS 9 และ 10 เบต้า:

1) สร้างคลาสย่อยสำหรับ UIButton (อย่าลืมตั้งคลาสแบบกำหนดเองสำหรับปุ่มใน Storyboard ด้วย)

2) แทนที่setTitle:forState:ดังต่อไปนี้:

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

    UIView.performWithoutAnimation({

        super.setTitle(title, forState: state)

        self.layoutIfNeeded()
    })
}

ในตัวสร้างส่วนต่อประสานคุณสามารถปล่อยให้ปุ่มประเภทเป็นระบบไม่จำเป็นต้องเปลี่ยนเป็นประเภทที่กำหนดเองสำหรับวิธีการนี้ในการทำงาน

ฉันหวังว่านี่จะช่วยให้คนอื่นฉันได้พยายามมานานแล้วด้วยปุ่มกะพริบที่น่ารำคาญที่ฉันหวังว่าจะหลีกเลี่ยงให้คนอื่น;)


อย่าลืมlayoutIfNeeded():]
Tai Le

6

คุณสามารถสร้างปุ่มกำหนดเองและมันจะหยุดเคลื่อนไหวในขณะที่เปลี่ยนชื่อ

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

คุณสามารถทำได้ในช่องทำเครื่องหมายกระดานเรื่องราว: เลือกปุ่มในกระดานเรื่องราว -> เลือกผู้ตรวจสอบคุณลักษณะ (ที่สี่จากด้านซ้าย) -> ในเมนูแบบเลื่อนลง 'ประเภท' เลือก 'กำหนดเอง' แทน 'ระบบ' ที่อาจถูกเลือก .

โชคดี!


3

คุณสามารถลบภาพเคลื่อนไหวออกจากเลเยอร์ของป้ายชื่อ:

    [[[theButton titleLabel] layer] removeAllAnimations];

ฉันผ่านทุกคำตอบ อันนี้ดีที่สุด
Rudolf Adamkovič

2
มันยังคงกะพริบ แต่ดีกว่า
Lucien

นี่ควรเป็นคำตอบ
mxcl

3

คำตอบ Xhacker Liu รุ่น Swift 4

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
} 

1

UIButton กับประเภทภาพเคลื่อนไหวมีนัยในsystem setTitle(_:for:)คุณสามารถแก้ไขได้สองวิธี:

  1. ตั้งค่าประเภทปุ่มcustomเป็นจากรหัสหรือเครื่องมือสร้างอินเตอร์เฟส:
let button = UIButton(type: .custom)

ป้อนคำอธิบายรูปภาพที่นี่

  1. ปิดใช้งานภาพเคลื่อนไหวจากรหัส:
UIView.performWithoutAnimation {
    button.setTitle(title, for: .normal)
    button.layoutIfNeeded()
}

0

ฉันพบว่าวิธีแก้ปัญหานี้ใช้งานได้กับUIButtonTypeSystemเช่นกัน แต่จะใช้ได้เฉพาะเมื่อเปิดใช้งานปุ่มด้วยเหตุผลบางประการ

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

ดังนั้นคุณจะต้องเพิ่มสิ่งเหล่านี้หากคุณต้องการปิดการใช้งานปุ่มเมื่อตั้งชื่อ

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

(iOS 7, Xcode 5)


เพิ่งยืนยันว่าวิธีแก้ปัญหานี้ไม่ทำงานบน iOS 7.1 อีกต่อไป
scha

ไม่คิดว่าคุณจะพบวิธีแก้ปัญหาสำหรับ 7.1?
George Green

@GeorgeGreen ไม่สามารถหาทางแก้ปัญหาการทำงานใด ๆ สำหรับUIButtonTypeSystem ผมใช้UIButtonTypeCustom
sCha

ตั้งแต่ 7.1 คุณจะต้องใช้การเปลี่ยนแปลงชื่อกับทุกรัฐตั้งค่าสำหรับสถานะปกติไม่ได้ใช้อีกต่อไป [_button setTitle:@"title" forState:UIControlStateDisabled]
แซม

0

การรวมคำตอบที่ดีข้างต้นให้ผลลัพธ์ในวิธีแก้ปัญหาต่อไปนี้สำหรับ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

ฉันมีปัญหาภาพเคลื่อนไหวที่น่าเกลียดเมื่อเปลี่ยนชื่อปุ่มในตัวควบคุมมุมมองภายใน UITabBarController ชื่อเรื่องที่ถูกตั้งค่าไว้ในกระดานเรื่องราวปรากฏตัวขึ้นครู่หนึ่งก่อนที่จะจางหายไปเป็นค่าใหม่ของพวกเขา

ฉันต้องการวนซ้ำตามการดูย่อยทั้งหมดและใช้ชื่อปุ่มเป็นกุญแจเพื่อรับค่าภาษาท้องถิ่นของพวกเขาด้วย NSLocalizedString เช่น;

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

}

ฉันพบว่าสิ่งที่กระตุ้นให้เกิดภาพเคลื่อนไหวคือสิ่งที่เรียกว่า btn.titleLabel.text ดังนั้นเพื่อให้ยังคงใช้กระดานเรื่องราวและมีการแปลเป็นภาษาท้องถิ่นแบบไดนามิกฉันแน่ใจว่าได้ตั้งค่า ID การคืนค่าของปุ่มทุกปุ่ม (ในตัวตรวจสอบตัวตน) ให้เหมือนกับชื่อและใช้เป็นคีย์แทนที่จะเป็นชื่อ

for(UIView *v in view.subviews) {

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

}

ไม่เหมาะ แต่ใช้งานได้


0

คุณสามารถตั้งค่าชื่อเรื่องนอกบล็อกแอนิเมชันตรวจสอบให้แน่ใจว่าได้โทรlayoutIfNeeded()เข้าไปภายใน 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()
}

หากคุณมีปุ่มมากมายลองพิจารณาlayoutIfNeeded()ดูในมุมมองระดับสูง:

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

0

นามสกุล Xhacker Liu แปลงเป็น Swift 3:

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

        setTitle(title, for: .normal)

        layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
}

-1

อาจสร้างภาพเคลื่อนไหว 2 ภาพและปุ่ม 2 ปุ่มเป็นวิธีแก้ปัญหาที่ดีกว่าเพื่อหลีกเลี่ยงปัญหาที่เกิดขึ้นกับการเคลื่อนไหวและการเปลี่ยนข้อความของปุ่ม?

ฉันสร้าง uibutton ตัวที่สองและสร้างแอนิเมชัน 2 ตัวโซลูชันนี้ใช้งานได้โดยไม่ต้อง hickups

    _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

ฉันได้มันไปทำงานร่วมกับคำตอบที่รวมกัน:

[[[button titleLabel] layer] removeAllAnimations];

    [UIView performWithoutAnimation:^{

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

    }];

-1

ส่วนขยายที่สะดวกสำหรับการเปลี่ยนชื่อปุ่มเคลื่อนไหวใน Swift ที่เล่นได้ดีกับการใช้งานเริ่มต้น:

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. คำตอบของฉันคือที่แตกต่างกัน 2. Up-to-date Swift ไวยากรณ์ 3. สอดคล้องกับ API ของ Apple UIButtonสำหรับ
Richard Topchii
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.