Сохранение UIButton, выбранного после касания
После того, как мой пользователь нажмет кнопку, я бы хотел, чтобы эта кнопка оставалась нажатой в течение времени, когда я выполняю сетевую операцию. Когда сетевая операция завершена, я хочу, чтобы кнопка вернулась к своему состоянию по умолчанию.
Я пробовал звонить - [UIButton setSelected:YES]
сразу после нажатия кнопки (с соответствующим вызовом - [UIButton setSelected:NO]
после завершения моей сети), но он ничего не делает. То же самое, если я назову setHighlighted:
.
Полагаю, я мог бы попытаться заменить фоновое изображение на выделенное состояние на время действия сети, но это похоже на взлома. Любые лучшие предложения?
Вот как выглядит мой код:
- (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;
}
Ответы
Ответ 1
Как вы устанавливаете изображения для разных 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)];
Edit:
Подводя свои замечания в комментариях и рассмотрим введенный вами код... вам нужно установить фоновые изображения для полного состояния UIControl
, в котором вы находитесь. Согласно вашему фрагменту кода это состояние управления будет отключена + выбрана + выделена на время работы сети. Это означает, что вам нужно будет сделать это:
[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateHighlighted|UIControlStateSelected)];
Если вы удалите highlighted = YES
, вам понадобится следующее:
[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateSelected)];
Получить изображение?
Ответ 2
У меня есть более простой способ. Просто используйте "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];
}
Ответ 3
"Все становится лучше, когда вы включаете питание"
button.selected = !button.selected;
работает отлично... после того, как я подключил выход к кнопке в построителе интерфейса.
Вам не нужно устанавливатьBackgroundImage: forState:, строитель позволяет вам указать фон (при необходимости изменить размер) или/или переднего плана (без изменения размера).
Ответ 4
Попробуйте использовать NSOperationQueue для этого. Попробуйте код следующим образом:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
theButton.highlighted = YES;
}];
Надеюсь, что это поможет.
Ответ 5
Используйте блок, поэтому вам не нужно создавать целый отдельный метод:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
theButton.highlighted = YES;
});
Update
Чтобы быть понятным, вам все равно нужно установить фон (или нормальное изображение) для состояний комбинации, а также обычные, например, sbrocket, в принятом ответе. В какой-то момент ваша кнопка будет выбрана и выделена, и у вас не будет изображения для этого, если вы не сделаете что-то вроде этого:
[button setBackgroundImage:someImage forState (UIControlStateHighlighted|UIControlStateSelected)];
В противном случае ваша кнопка может вернуться к изображению UIControlStateNormal для краткого выбранного + выделенного состояния, и вы увидите вспышку.
Ответ 6
В быстром я делаю это следующим образом.
Я создаю подкласс 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
}
}
}
Прекрасно подходит для меня.
Ответ 7
У меня была аналогичная проблема, когда я хотел, чтобы кнопка удерживала ее после клика.
Проблема в том, что если вы попытаетесь использовать setHighlighted:YES
внутри вашего действия click, он будет reset сразу после нажатия действия, - (IBAction)checkInButtonPushed
Я решил это, используя NSTimer, как этот
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.01
target: self
selector: @selector(selectCurrentIndex)
userInfo: nil
repeats: NO];
а затем вызовите setHighlighted:YES
из моего метода selectCurrentIndex
. Я использую обычные кнопки UIButtonTypeRoundedRect
.
Ответ 8
У меня есть другой способ... если вы не хотите использовать изображения и хотите эффект нажатой кнопки, вы можете подклассифицировать кнопку и здесь мой код:
в файле .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;
}
} `
Ответ 9
Вот реализация С#/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;
});
});
};