Utrzymanie UIButton wybrany po dotknięciu

Gdy mój użytkownik kliknie przycisk, chciałbym, aby ten przycisk pozostał wciśnięty podczas wykonywania operacji sieciowej. Po zakończeniu operacji sieciowej chcę, aby przycisk wrócił do stanu domyślnego.

Próbowałem wywołać - [UIButton setSelected:YES] zaraz po naciśnięciu przycisku (z odpowiednim wywołaniem do -[UIButton setSelected:NO] po zakończeniu operacji sieciowej), ale wydaje się, że nic nie robi. To samo, jeśli zadzwonię setHighlighted:.

Myślę, że mógłbym spróbować podmienić obraz tła, aby określić wybrany stan na czas trwania operacji sieciowej, ale to wygląda na włamanie. Jakieś lepsze propozycje?

Oto jak wygląda mój kod:

- (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;
}
Author: Parth Bhatt, 2009-11-23

9 answers

Jak ustawić obrazy dla różnych UIControlStates na przycisku? Czy ustawiasz obraz tła dla UIControlStateHighlighted oraz UIControlStateSelected?

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

Jeśli ustawiasz wybrany stan na przycisku Dotknij w dół zdarzenia, a nie dotykać wewnątrz, twój przycisk będzie rzeczywiście w podświetlony + wybrany stan, więc będziesz chciał ustawić, że zbyt.

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

Edit:

Aby podsumować moje uwagi w komentarzach i odnieść się do kodu, który zamieściłeś...musisz ustawić swoje tło obrazy dla pełnej UIControl stwierdzają, że jesteś w. Zgodnie z Twoim urywkiem kodu, ten stan kontroli będzie wyłączony + zaznaczony + podświetlony na czas działania sieci. Oznacza to, że musisz to zrobić:

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

Jeśli usuniesz highlighted = YES, będziesz potrzebował tego:

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

Rozumiesz?

 73
Author: Bryan Henry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-13 17:17:36

Mam łatwiejszy sposób. Wystarczy użyć "performSelector" z opóźnieniem 0, aby wykonać [button setHighlighted:YES] . Spowoduje to ponowne podświetlenie po zakończeniu bieżącego 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];
}
 29
Author: Hlung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-05 09:16:11

"wszystko staje się lepsze, gdy włączasz zasilanie"

    button.selected = !button.selected;
Działa idealnie... po podłączeniu gniazdka do przycisku w Kreatorze interfejsów.

Nie musisz ustawiaćbackgroundimage:forState:, konstruktor pozwala określić tło (w razie potrzeby zmienia rozmiar) lub/i pierwszy plan (nie zmienia rozmiaru) obrazów.

 27
Author: 18446744073709551615,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-20 17:20:14

Spróbuj użyć NSOperationQueue, aby to osiągnąć. Wypróbuj kod w następujący sposób:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    theButton.highlighted = YES;
}];
Mam nadzieję, że to pomoże.
 27
Author: roberto.buratti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-07 18:17:04

Użyj bloku, więc nie musisz budować całej oddzielnej metody:

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

Update

Aby było jasne, nadal musisz ustawić tło (lub normalny obraz) dla Stanów kombinacji, jak również te zwykłe, jak mówi sbrocket w zaakceptowanej odpowiedzi. W pewnym momencie twój przycisk będzie zarówno zaznaczony, jak i podświetlony, i nie będziesz mieć do tego obrazu, chyba że zrobisz coś takiego:

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

W przeciwnym razie twój przycisk może wrócić do obrazu UIControlStateNormal na krótki zaznaczony + podświetlony stan i zobaczysz błysk.

 8
Author: Bob Spryn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-30 21:50:13

W swift robię to jak poniżej.

Stworzyłem podklasę UIButton i zaimplementowałem własną właściwość 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
        }
    }

}
Dla mnie działa idealnie.
 2
Author: Eike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-16 12:19:35

Miałem podobny problem, gdzie chciałem przycisk, aby zachować to podświetlenie po kliknięciu. Problem polega na tym, że jeśli spróbujesz użyć setHighlighted:YES wewnątrz kliknięcia akcji, zostanie to zresetowane zaraz po kliknięciu akcji, - (IBAction)checkInButtonPushed

Rozwiązałem to używając takiego Nstimera

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

A następnie wywołaj {[1] } z mojej metody selectCurrentIndex. Używam zwykłych UIButtonTypeRoundedRect przycisków.

 1
Author: fredrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-11 22:52:59

Mam inny sposób ...jeśli nie chcesz używać obrazów, a chcesz efekt wciśniętego przycisku, możesz podklasować przycisk i oto mój kod:

W .plik h:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

W .plik 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
Author: Pach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-30 14:39:23

Oto C # / MonoTouch (Xamarin.iOS) wdrożenie z wykorzystaniem podejść przedstawionych powyżej. Zakłada, że stan podświetlonego obrazu został już ustawiony, a Stany zaznaczone i zaznaczone|podświetlone zostaną skonfigurowane tak, aby korzystały z tego samego obrazu.

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;
        });
    });
};
 0
Author: t9mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-24 02:36:17