การเลือก UIButton ไว้หลังจากสัมผัส


90

หลังจากที่ผู้ใช้ของฉันคลิกปุ่มฉันต้องการให้ปุ่มนั้นยังคงอยู่ในช่วงเวลาที่ฉันดำเนินการเครือข่าย เมื่อการทำงานของเครือข่ายเสร็จสมบูรณ์ฉันต้องการให้ปุ่มกลับสู่สถานะเริ่มต้น

ฉันได้ลองโทร - [UIButton setSelected:YES]ทันทีหลังจากกดปุ่ม (พร้อมกับการโทรที่เกี่ยวข้องกับ - [UIButton setSelected:NO]หลังจากการปิดเครือข่ายของฉันเสร็จสิ้น) แต่ดูเหมือนจะไม่ทำอะไรเลย เหมือนกันถ้าฉันโทรsetHighlighted:.

ฉันคิดว่าฉันสามารถลองเปลี่ยนภาพพื้นหลังเพื่อแสดงสถานะที่เลือกในช่วงระยะเวลาของเครือข่าย op แต่ดูเหมือนว่าจะเป็นการแฮ็ก ข้อเสนอแนะที่ดีกว่านี้?

นี่คือลักษณะของรหัสของฉัน:

- (IBAction)checkInButtonPushed
{
    self.checkInButton.enabled = NO;
    self.checkInButton.selected = YES;
    self.checkInButton.highlighted = YES;
    [self.checkInActivityIndicatorView startAnimating];
    [CheckInOperation startWithPlace:self.place delegate:self];
}

- (void)checkInCompletedWithNewFeedItem:(FeedItem*)newFeedItem wasNewPlace:(BOOL)newPlace possibleError:(NSError*)error;
{
    [self.checkInActivityIndicatorView stopAnimating];
    self.checkInButton.enabled = YES;
    self.checkInButton.selected = NO;
    self.checkInButton.highlighted = NO;
}

คำตอบ:


73

คุณตั้งค่ารูปภาพให้แตกต่างกันอย่างไรUIControlStatesบนปุ่ม? คุณกำลังตั้งค่าภาพพื้นหลังสำหรับUIControlStateHighlightedเช่นเดียวกับUIControlStateSelected?

UIImage *someImage = [UIImage imageNamed:@"SomeResource.png"];
[button setBackgroundImage:someImage forState:UIControlStateHighlighted];
[button setBackgroundImage:someImage forState:UIControlStateSelected];

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

[button setBackgroundImage:someImage forState:(UIControlStateHighlighted|UIControlStateSelected)];

แก้ไข:

เพื่อสรุปความคิดเห็นของฉันในความคิดเห็นและเพื่อระบุรหัสที่คุณโพสต์ ... คุณต้องตั้งค่าภาพพื้นหลังของคุณสำหรับUIControlสถานะเต็มที่คุณอยู่ตามข้อมูลโค้ดของคุณสถานะการควบคุมนี้จะถูกปิดใช้งาน + เลือก + ไฮไลต์สำหรับระยะเวลาการทำงานของเครือข่าย ซึ่งหมายความว่าคุณจะต้องทำสิ่งนี้:

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateHighlighted|UIControlStateSelected)];

หากคุณลบออกhighlighted = YESคุณจะต้องมีสิ่งนี้:

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateSelected)];

ได้ภาพ?


ฉันเชื่อว่าฉันกำลังทำตามที่คุณแนะนำ ฉันแค่ทำผ่าน Interface Builder ฉันเพิ่มรหัสที่ฉันใช้กับคำถามด้านบน ... บางทีนั่นอาจทำให้เกิดปัญหาขึ้นบ้าง? ลักษณะการทำงานที่ฉันต้องการคือฉันต้องการให้ปุ่มยังคงถูกเลือกตลอดระยะเวลาการทำงานของเครือข่ายของฉัน สิ่งที่ฉันเห็นคือปุ่มไฮไลต์เมื่อแตะจากนั้นไฮไลต์จะหายไปเมื่อแตะเสร็จสิ้น ปุ่ม -never- ถูกเลือก ทำไมสิ่งนี้ถึงไม่ได้ผลสำหรับฉันฉันจึงรู้สึกว่าฉันทำอะไรโง่ ๆ ฉันได้ตรวจสอบการเชื่อมต่อ IB ทั้งหมดแล้วและทำได้ดี ...
Greg Maletic

ฉันไม่เชื่อว่าคุณสามารถตั้งค่าภาพพื้นหลังสำหรับสถานะที่ไฮไลต์ + ที่เลือกในตัวสร้างอินเทอร์เฟซได้เฉพาะสถานะที่ไฮไลต์และที่เลือกแยกกัน หากปุ่มของคุณอยู่ในสถานะที่ไฮไลต์และเลือกไว้ถูกตั้งค่าไว้ทั้งคู่ฉันเชื่อว่าค่าเริ่มต้นจะเป็นรูปภาพปกติของคุณไม่ใช่รูปภาพที่ไฮไลต์หรือที่เลือกไว้ จากรหัสของคุณคุณกำลังตั้งค่าสถานะของปุ่มเพื่อให้ทั้งที่เลือกและไฮไลต์เป็นใช่ checkInButtonPushed เชื่อมต่อกับ "Touch Up Inside" หรืออย่างอื่นหรือไม่
Bryan Henry

ใช่มันเชื่อมต่อกับ "Touch Up Inside" และถ้าฉันลบรหัสที่เกี่ยวข้องกับสถานะ "ไฮไลต์" ออกก็ยังใช้ไม่ได้ สถานะ "เลือก" จะไม่ปรากฏขึ้น
Greg Maletic

นอกจากนี้ทำไมคุณจึงปิดใช้งานปุ่มนี้? นั่นหมายความว่าสถานะปุ่มถูกปิดใช้งาน + เน้น + เลือกไว้ หากคุณลบการตั้งค่าบรรทัดที่ไฮไลต์เป็น YES แสดงว่าคุณได้ปิดใช้งาน + เลือกไว้ดังนั้นคุณต้องตั้งค่ารูปภาพสำหรับสถานะ (UIControlStateDisabled | UIControlStateSelected)
Bryan Henry

โอเคนั่นคือปัญหา เมื่อฉันนำฟังก์ชันปิดการใช้งานออกมามันก็ทำงานได้ตามที่คาด ขอบคุณ! (เพื่อตอบคำถามของคุณฉันกำลังปิดใช้งานปุ่มนี้เพราะฉันไม่ต้องการให้ใครกดปุ่มนี้อีกในขณะที่การทำงานของเครือข่ายกำลังดำเนินต่อไป)
Greg Maletic

30

ฉันมีวิธีที่ง่ายกว่านั้น ใช้เพียงแค่ "performSelector" กับ 0 [button setHighlighted:YES]ความล่าช้าในการดำเนินการ การดำเนินการนี้จะทำการไฮไลต์ซ้ำหลังจากที่ runloop ปัจจุบันสิ้นสุดลง

- (IBAction)buttonSelected:(UIButton*)sender {
    NSLog(@"selected %@",sender.titleLabel.text);
    [self performSelector:@selector(doHighlight:) withObject:sender afterDelay:0];
}

- (void)doHighlight:(UIButton*)b {
    [b setHighlighted:YES];
}

28

"ทุกอย่างจะดีขึ้นเมื่อคุณเปิดเครื่อง"

    button.selected = !button.selected;

ทำงานได้อย่างสมบูรณ์ ... หลังจากที่ฉันเชื่อมต่อเต้าเสียบกับปุ่มในตัวสร้างส่วนต่อประสาน

คุณไม่จำเป็นต้อง setBackgroundImage: forState: ตัวสร้างอนุญาตให้คุณระบุพื้นหลัง (ได้รับการปรับขนาดหากจำเป็น) หรือ / และภาพเบื้องหน้า (ไม่ปรับขนาด)


27

ลองใช้ NSOperationQueue เพื่อบรรลุเป้าหมายนี้ ลองใช้รหัสดังนี้:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    theButton.highlighted = YES;
}];

หวังว่านี่จะช่วยได้


นี่เป็นทางออกที่ยอดเยี่ยม Roberto & Parth อย่างไรก็ตามรายละเอียดเล็ก ๆ อย่างหนึ่งก็คือคุณจะเห็น "การสั่นไหว" เป็นครั้งคราวหากผู้ใช้กดนิ้วลงบนปุ่ม มีวิธีใดบ้างที่จะป้องกันการสั่นไหว?
Scott Lieberman

8

ใช้บล็อกเพื่อให้คุณไม่ต้องสร้างวิธีการแยกทั้งหมด:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
    theButton.highlighted = YES;
});

อัปเดต

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

[button setBackgroundImage:someImage forState (UIControlStateHighlighted|UIControlStateSelected)];

มิฉะนั้นปุ่มของคุณสามารถถอยกลับไปที่ภาพ UIControlStateNormal สำหรับสถานะที่เลือก + เน้นสั้น ๆ แล้วคุณจะเห็นแฟลช


FYI dispatch_get_current_queue()ถูกระบุว่า "ไม่น่าเชื่อถือ"
Jacob Relkin

1
ระบุไว้ที่ไหน? ทางเลือกคืออะไร?
Bob Spryn

มีความสำคัญในการใช้dispatch_afterตรงข้ามกับdispatch_async?
Ilya

ใช่. dispatch_asyncเป็นทางเลือกที่ดีกว่า
Bob Spryn

4

อย่างรวดเร็วฉันจะทำดังต่อไปนี้

ฉันสร้างคลาสย่อยUIButtonและใช้คุณสมบัติที่กำหนดเองstate

class ActiveButton: UIButton {

    private var _active = false
    var active:Bool {
        set{
            _active = newValue
            updateState()
        }
        get{
            return _active
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.addTarget(self, action: #selector(ActiveButton.touchUpInside(_:)), forControlEvents: .TouchUpInside)
    }

    func touchUpInside(sender:UIButton) {
        active = !active
    }

    private func updateState() {
        NSOperationQueue.mainQueue().addOperationWithBlock {
            self.highlighted = self.active
        }
    }

}

ทำงานได้ดีสำหรับฉัน


1

ฉันมีปัญหาคล้ายกันที่ฉันต้องการปุ่มเพื่อให้มันไฮไลต์หลังจากคลิก ปัญหาคือถ้าคุณพยายามใช้setHighlighted:YESภายในของคุณคลิกการกระทำมันจะรีเซ็ตทันทีที่คุณคลิกการกระทำ- (IBAction)checkInButtonPushed

ฉันแก้ไขสิ่งนี้โดยใช้ NSTimer แบบนี้

NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.01
                                         target: self
                                       selector: @selector(selectCurrentIndex)
                                       userInfo: nil
                                        repeats: NO];

แล้วโทรsetHighlighted:YESจากselectCurrentIndexวิธีการของฉัน ฉันใช้UIButtonTypeRoundedRectปุ่มปกติ


0

ฉันมีวิธีอื่น ... ถ้าคุณไม่ต้องการใช้รูปภาพและคุณต้องการเอฟเฟกต์ของปุ่มที่กดคุณสามารถคลาสย่อยของปุ่มและนี่คือรหัสของฉัน:

ในไฟล์. h:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

ในไฟล์. m:

#import <QuartzCore/QuartzCore.h>


 @implementation reservasButton

 -(void)setupView {  //This is for Shadow

    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOpacity = 0.5; 
    self.layer.shadowRadius = 1;    
    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); //comment
    //   self.layer.borderWidth = 1;
    self.contentVerticalAlignment   = UIControlContentVerticalAlignmentCenter;
    self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;

    // [self setBackgroundColor:[UIColor whiteColor]];

    //  self.opaque = YES;


}

-(id)initWithFrame:(CGRect)frame{
    if((self = [super initWithFrame:frame])){
        [self setupView];
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if((self = [super initWithCoder:aDecoder])){
        [self setupView];
    }

    return self;
}

//Here is the important code

 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{


  if (isPressed == FALSE) {

      self.contentEdgeInsets = UIEdgeInsetsMake(1.0,1.0,-1.0,-1.0);
      self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
      self.layer.shadowOpacity = 0.8;

      [super touchesBegan:touches withEvent:event];

      isPressed = TRUE;

     }
     else {

         self.contentEdgeInsets = UIEdgeInsetsMake(0.0,0.0,0.0,0.0);
         self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);
         self.layer.shadowOpacity = 0.5;

         [super touchesEnded:touches withEvent:event];

         isPressed = FALSE;

     }


 } `

0

นี่คือการใช้งาน C # / MonoTouch (Xamarin.iOS) โดยใช้แนวทางที่นำเสนอข้างต้น ถือว่าคุณได้ตั้งค่าสถานะภาพไฮไลต์ไว้แล้วและกำหนดค่าสถานะที่เลือกและเลือก | ไฮไลต์เพื่อใช้ภาพเดียวกัน

var selected = button.BackgroundImageForState(UIControlState.Highlighted);
button.SetBackgroundImage(selected, UIControlState.Selected);
button.SetBackgroundImage(selected, UIControlState.Selected | UIControlState.Highlighted);
button.TouchUpInside += delegate
{
    NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(0), delegate
    {
        button.Highlighted = true;
        NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(200), delegate
        {
            button.Highlighted = false;
        });
    });
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.