Gdy użytkownik kliknie przycisk, chciałbym, aby ten przycisk pozostawał wciśnięty przez cały czas wykonywania operacji sieciowych. Po zakończeniu operacji sieciowej chcę, aby przycisk powrócił do stanu domyślnego.
Próbowałem dzwonić - [UIButton setSelected:YES]
zaraz po naciśnięciu przycisku (z odpowiednim wywołaniem - [UIButton setSelected:NO]
po zakończeniu operacji w sieci), ale wydaje się, że nic nie daje. To samo, jeśli zadzwonię setHighlighted:
.
Przypuszczam, że mógłbym spróbować zamienić obraz tła, aby wskazać wybrany stan na czas trwania operacji sieciowej, ale wygląda to na włamanie. Jakieś lepsze sugestie?
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;
}
Mam łatwiejszy sposób. Po prostu użyj "performSelector" z 0 opóźnieniem, 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]; }
źródło
„Wszystko staje się lepsze, gdy włączysz zasilanie”
button.selected = !button.selected;
działa idealnie ... po podłączeniu gniazdka do przycisku w Interface Builder.
Nie musisz ustawiaćBackgroundImage: forState :, kreator umożliwia określenie tła (w razie potrzeby zostanie zmieniony rozmiar) lub / i pierwszego planu (bez zmiany rozmiaru).
źródło
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.
źródło
Użyj bloku, aby nie musieć budować całej oddzielnej metody:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{ theButton.highlighted = YES; });
Aktualizacja
Aby było jasne, nadal musisz ustawić tło (lub normalny obraz) dla stanów kombinacji, a także zwykłych, takich jak sbrocket w zaakceptowanej odpowiedzi. W pewnym momencie twój przycisk zostanie 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 UIControlStateNormal obrazu dla krótkiego wybranego + podświetlonego stanu, a zobaczysz flash.
źródło
dispatch_get_current_queue()
jest określane jako „niewiarygodne”.dispatch_after
w przeciwieństwie dodispatch_async
?dispatch_async
to lepszy wybór.Szybko robię to jak poniżej.
Tworzę podklasę
UIButton
i zaimplementowałem właściwość niestandardową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 } } }
U mnie działa idealnie.
źródło
Miałem podobny problem, gdy chciałem, aby przycisk pozostawał podświetlony po kliknięciu. Problem polega na tym, że jeśli spróbujesz użyć
setHighlighted:YES
wewnątrz akcji kliknięcia, zresetuje się ona natychmiast po kliknięciu akcji,- (IBAction)checkInButtonPushed
Rozwiązałem to używając NSTimer takiego jak ten
NSTimer *timer; timer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(selectCurrentIndex) userInfo: nil repeats: NO];
a następnie zadzwoń
setHighlighted:YES
z mojejselectCurrentIndex
metody. Używam zwykłychUIButtonTypeRoundedRect
przycisków.źródło
Mam inny sposób ... jeśli nie chcesz używać obrazów, a chcesz efektu wciśniętego przycisku, możesz podklasować Button i oto mój kod:
w pliku .h:
@interface reservasButton : UIButton { BOOL isPressed; } @end
W pliku .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; } } `
źródło
Oto implementacja C # / MonoTouch (Xamarin.iOS) przy użyciu metod przedstawionych powyżej. Zakłada się, że ustawiłeś już stan Highlighted image i konfiguruje wybrane i wybrane | wyróżnione stany tak, aby używały 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; }); }); };
źródło