如何在UI线程上刷一个按钮? [英] How to flash a button on UI thread?

查看:166
本文介绍了如何在UI线程上刷一个按钮?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按下按钮后,我的UI上有一个按钮,我想每800毫秒闪烁一次(然后再打开然后再关闭)。我使用以下代码执行此操作:

I have a button on my UI that I would like to flash (turn on and then off again) every 800ms, once the button has been pressed. I do that with the following code:

- (void)flickEmergencyButton {
  // Check whether an emergency is in progress...
  if (model.emergencyInProgress) {
    // ...and if so, flick the state
    self.emergencyButton.selected = !self.emergencyButton.selected;

    // Make this method be called again in 800ms
    [self performSelector:@selector(flickEmergencyButton) withObject:nil afterDelay:0.8];
  } else {
    // ...otherwise, turn the button off
    self.emergencyButton.selected = NO;
  }
}

...哪种方法效果很好,除了:那里UI上也是一个UIScrollView,当用户用手指向下滚动并滚动时,按钮会冻结。虽然我完全理解为什么会这样,但我不知道该怎么做。

...which works really well, except: There is a UIScrollView on the UI as well and while the user has his finger down on it and is scrolling around, the button freezes. While I completely understand why that is, I am not sure what to do about it.

performSelector:withObject:afterDelay 消息调度要在当前线程上发送的消息,这是主线程,即。在所有其他UI活动结束之前,UI处理并因此无法处理消息。正确?但我需要在UI线程上执行此操作,因为我无法选择/取消选择任何其他线程上的按钮,对吧?那么这里的解决方案是什么?

The performSelector:withObject:afterDelay message schedules the message to be send on the current thread, which is the main thread, ie. the UI tread and hence does not get to process the message until all other UI activity has come to an end. Correct? But I need to do this on the UI thread as I cannot select/un-select the button on any other thread, right? So what is the solution here?

推荐答案

我建议使用Core Animation。尝试这样的事情:

I would recommend using Core Animation. Try something like this:

-(void) flash{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];

    if( emergency ){       
        // Start flashing
        [UIView setAnimationRepeatCount:1000];
        [UIView setAnimationRepeatAutoreverses:YES];

        [btn setAlpha:0.0f];        
    }else{
        // Stop flashing
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationRepeatCount:1];

        [btn setAlpha:1.0f];        
    }
    emergency = !emergency;
    [UIView commitAnimations];
}

其中btn被声明为

@property(nonatomic, retain) IBOutlet UIButton *btn;

和紧急是一个简单的BOOL变量。

and emergency is a simple BOOL variable.

调用闪光灯开始并停止动画。

Call flash to start and to stop the animation.

在这个例子中,为了简单起见,我们为alpha属性设置了动画,但你也可以使用按钮backcolor进行相同操作,如Sam在他的回答中说,或者你喜欢的任何属性。

In this example we animate the alpha attribute for simplicity, but you can do the same with the button backcolor, as Sam said in his answer, or whatever attribute you like.

希望它有所帮助。

UPDATE :

关于在两张图片之间进行转换,请尝试调用 imageFlash 而不是 flash

Regarding making the transition between two images, try calling imageFlash instead of flash:

-(void) imageFlash{

    CABasicAnimation *imageAnimation = [CABasicAnimation animationWithKeyPath:@"contents"];
    [btn setImage:normalState forState:UIControlStateNormal];

    if( emergency ){        
        imageAnimation.duration = 0.5f;
        imageAnimation.repeatCount = 1000;
    }else{
        imageAnimation.repeatCount = 1;
    }

    imageAnimation.fromValue = (id)normalState.CGImage;
    imageAnimation.toValue = (id)emergencyState.CGImage;    
    [btn.imageView.layer addAnimation:imageAnimation forKey:@"animateContents"];    
    [btn setImage:normalState forState:UIControlStateNormal]; // Depending on what image you want after the animation.

    emergency = !emergency;
}

其中 normalState emergencyState 是您要使用的图片:

Where normalState and emergencyState are the images you want to use:

声明为:

UIImage *normalState;
UIImage *emergencyState;

分配图像:

normalState = [UIImage imageNamed:@"normal.png"];
emergencyState = [UIImage imageNamed:@"alert.png"];

祝你好运!

这篇关于如何在UI线程上刷一个按钮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆