1

ボタンが押されると、UI に 800ms ごとに点滅させたい (オンにしてからオフにする) ボタンがあります。私は次のコードでそれを行います:

- (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 アクティビティが終了するまでメッセージを処理できません。正しい?しかし、他のスレッドではボタンを選択/選択解除できないため、UI スレッドでこれを行う必要がありますよね? それで、ここでの解決策は何ですか?

4

2 に答える 2

4

Core Animation の使用をお勧めします。次のようなことを試してください:

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

また、emergency は単純な BOOL 変数です。

アニメーションを開始および停止するには、flash を呼び出します。

この例では、簡単にするためにアルファ属性をアニメーション化しますが、サムが答えで言ったように、ボタンの背景色、または好きな属性で同じことを行うことができます.

それが役に立てば幸い。

アップデート:

imageFlash2 つの画像間の遷移に関しては、代わりに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

次のように宣言されています。

UIImage *normalState;
UIImage *emergencyState;

画像の割り当て:

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

幸運を!

于 2011-08-01T18:09:38.640 に答える
3

CoreAnimationこれは(おそらくbackgroundColorカスタムのアニメーション化)の仕事のように感じますが、適切な実行ループモードで実行する ことでUIControlこれを達成できます。NSTimer

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のドキュメントには、実行ループモードと一般的な実行ループのより詳細な説明が記載されています。

于 2011-08-01T03:19:31.363 に答える