2011-08-01 23 views
1

我在用戶界面上有一個按鈕,每按下一次按鈕,我就會每隔800毫秒閃一下(打開然後再關閉)。我這樣做,用下面的代碼:如何刷新UI線程上的按鈕?

- (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,以及和在用戶有他的手指放在上面並圍繞,滾動按鈕凍結。雖然我完全理解這是爲什麼,但我不知道該怎麼做。

performSelector:withObject:afterDelay消息調度要在當前線程(即主線程)上發送的消息,即,用戶界面踩點,因此在所有其他用戶界面活動結束之前都無法處理該消息。正確?但我需要在UI線程上這樣做,因爲我無法選擇/取消選擇任何其他線程上的按鈕,對不對?那麼這裏的解決方案是什麼?

+0

難道你不能只用選項* UIViewAnimationOptionRepeat *或* UIViewAnimationOptionAutoreverse * set添加動畫到按鈕嗎? –

回答

4

我會建議使用核心動畫。嘗試是這樣的:

-(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; 

和應急是一個簡單的布爾變量。

來電閃啓動和停止動畫。

在這個例子中,我們對動畫的簡單阿爾法屬性,但你可以做的按鈕,背景色相同,山姆在他回答說,或任何屬性你喜歡的。

希望它有幫助。

UPDATE:

關於使兩幅圖像之間的過渡,嘗試調用imageFlash而不是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; 
} 

normalStateemergencyState是您要使用的圖像:

宣稱爲:

UIImage *normalState; 
UIImage *emergencyState; 

將圖像生成:

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

祝你好運!

+0

謝謝你。這是一個好主意;出於某種原因,我根本沒有想到Core Animation ......但是,我的按鈕由兩個圖像組成:一個用於關閉,一個用於打開。有兩種動畫方式可以在兩幅圖像之間切換嗎? – McKrassy

+0

查看更新回答:) –

3

雖然這種感覺就像爲CoreAnimation工作(也許動畫自定義UIControlbackgroundColor),你可以在適當的運行循環模式運行的NSTimer做到這一點。

e.x.

NSTimer *timer = [NSTimer timerWithTimeInterval:0.8f target:self selector:@selector(flicker:) userInfo:nil repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

,當你想停止動畫:

[timer invalidate], timer = nil; 
button.selected = NO; 

通過添加定時器所有NSRunLoopCommonModes,你不僅將其添加到默認的運行循環模式,但該模式是在同時,用戶交互正在連續處理(UITrackingRunLoopMode)。

Apple's docs給出了對運行循環模式和運行循環的更全面的解釋。