Pergunta

Depois que meu usuário clica em um botão, eu gostaria que esse botão fique pressionado durante o tempo em que eu execute uma operação de rede. Quando a operação da rede estiver concluída, quero que o botão retorne ao seu estado padrão.

Eu tentei ligar -[UIButton setSelected:YES] logo após o botão empurrar (com uma chamada correspondente para -[UIButton setSelected:NO] Após o meu término da minha rede), mas parece não fazer nada. A mesma coisa se eu ligar setHighlighted:.

Suponho que poderia tentar trocar a imagem em segundo plano para denotar um estado selecionado durante a duração do Network Op, mas isso parece um hack. Alguma sugestão melhor?

Aqui está como é o meu código:

- (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;
}
Foi útil?

Solução

Como você está definindo as imagens para os diferentes UIControlStates no botão? Você está definindo uma imagem de fundo para UIControlStateHighlighted assim como UIControlStateSelected?

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

Se você estiver definindo o estado selecionado no evento Button Touch, em vez de encerrar, seu botão estará realmente em um estado destacado+selecionado, então você também deve definir isso.

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

Editar:

Para resumir minhas observações nos comentários e abordar o código que você postou ... você precisa definir suas imagens de fundo para o completo UIControl Declare que você está. De acordo com o seu snippet de código, esse estado de controle seria desativado + selecionado + destacado para a duração da operação de rede. Isso significa que você precisaria fazer isso:

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

Se você remover o highlighted = YES, então você precisaria disso:

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

Obter a foto?

Outras dicas

Eu tenho uma maneira mais fácil. Basta usar o "PerformSelector" com 0 atraso para executar [button setHighlighted:YES] . Isso executará a luz de destaque após o final do Runloop atual.

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

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

"Tudo fica melhor quando você liga"

    button.selected = !button.selected;

Funciona perfeitamente ... depois de conectar a tomada ao botão no construtor de interface.

Você não precisa ser contratante: forstate:, o construtor permite especificar o plano de fundo (é redimensionado, se necessário) ou/e em primeiro plano (não redimensionando).

Tente usar o NsoperationQueue para conseguir isso. Experimente o código da seguinte maneira:

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

Espero que isto ajude.

Use um bloco para que você não precise construir um método totalmente separado:

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

Atualizar

Para ficar claro, você ainda precisa definir o plano de fundo (ou imagem normal) para os estados combinados, bem como os regulares como Sbrocket diz na resposta aceita. Em algum momento, seu botão será selecionado e destacado, e você não terá uma imagem para isso, a menos que faça algo assim:

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

Caso contrário, seu botão poderá voltar à imagem UiControlStatEnormal para o breve estado selecionado+destacado e você verá um flash.

Em Swift, estou fazendo isso como o seguinte.

Eu crio uma subclasse de UIButton e implementou uma propriedade personalizada 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
        }
    }

}

Funciona perfeitamente para mim.

Eu tive um problema semelhante em que queria um botão para manter o destaque após o clique. O problema é se você tentar usar setHighlighted:YES Dentro de você, clique em Ação, ele será redefinido logo após você clicar em Ação, - (IBAction)checkInButtonPushed

Eu resolvi isso usando um nstimer como este

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

e então ligue setHighlighted:YES do meu selectCurrentIndex método. Eu uso regular UIButtonTypeRoundedRect botões.

Eu tenho outra maneira ... se você não quiser usar imagens e deseja o efeito de um botão pressionado, você pode subclasse o botão e aqui está o meu código:

No arquivo .h:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

No arquivo .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;

     }


 } `

Aqui está uma implementação C# / Monotouch (xamarin.ios) usando abordagens apresentadas acima. Ele assume que você já definiu o estado de imagem destacado e configura os estados selecionados e selecionados | destacados para usar a mesma imagem.

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;
        });
    });
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top