0

私はプログラムを持っています。私は音楽ノートを演奏するはずのアンドロイドスタジオで書き込みをしています。座標、曲名、時間のアーリーリストに基づいてサイズを拡大していますノートを演奏する。しかし、私が抱えている問題は、すべての音符が正しく再生されていることです。しかし最後の円だけが描画されますすべての音符を再生するループを終了した後。私はこの質問を以前に調べましたが、setWillNotDraw(false);を呼び出すことについていくつかの回答がありましたが、私はそれを私のコンストラクタで呼び出しましたが、私はまだ同じ問題を抱えています。私は複数の異なる場所でinvalidate();を呼び出すことを試みましたが、何も動作していないようです。どんな助けでも大歓迎です!OnDraw()はループ後に一度だけ呼び出されます

マイコード:

コンストラクタ

public PlayView(Context context, @Nullable AttributeSet attrs) { 
    super(context, attrs); 
    saver = PersistentSaver.getInstance(context); 
    this.context=context; 
    setWillNotDraw(false); 
} 

@Override 
public void onDraw(Canvas canvas){ 
    super.onDraw(canvas); 
    this.canvas=canvas; 
    if(mCurrentRect !=null&& colorPaint!=null) { 
     canvas.drawOval(mCurrentRect, colorPaint); 
    } 
} 

私がチェックしたnotes-を再生するループを描き、すべての円座標とノートが正しい配列に含まれています:

public void playSong(){ 
    String song = saver.getCurrSongName(); 
    ArrayList<Long> Times = saver.getTimesForNotes(song); 
    ArrayList<Float> xCoordinates = saver.getPressXCoordinates(song); 
    ArrayList<Float> yCoordinates = saver.getPressYCoordinates(song); 
    ArrayList<String> notes = saver.getNotesForSong(song); 
    for(int i=0;i<Times.size();i++) { 
     //pause until correct time. TODO: ADJUST ERROR BOUND 
     while (true) { 
      currTime = System.currentTimeMillis() - startTime; 
      if (currTime <= Times.get(i) + epsilon && currTime >= Times.get(i) - epsilon) break; 
     } 
     //play note with that x and y coordinate and draw circle 
     playNote(xCoordinates.get(i), yCoordinates.get(i), notes.get(i)); 
    } 
} 

コードは、ノートやサウンドを再生します

private void playNote(float pressx, float pressy, String note){ 
    colorPaint=new Paint(); 
    colorPaint.setStyle(Paint.Style.STROKE); 
    colorPaint.setStrokeWidth(10); 
    colorPaint.setColor(generateColor(pressx,pressy)); 
    float translateX = 50.0f; 
    float translateY = 50.0f; 
    Random rand = new Random(10000); 
    int xr = rand.nextInt(); 
    int yr = rand.nextInt(); 
    int startColor = generateColor(pressx,pressy); 
    int midColor = generateColor(pressx+rand.nextInt(),pressy+rand.nextInt()); 
    int endColor = generateColor(pressx+xr,pressy+yr); 
    mCurrentRect = new AnimatableRectF(pressx-50,pressy-50,pressx+50,pressy+50); 
    debugx=pressx; 
    playAnimation(startColor,midColor,endColor, translateX, translateY); 
    playSound(note); 
} 

アニメーションを再生するにはを想定しているが、ループが終了した後にのみonDraw();を呼び出しているコード

private void playAnimation(int startColor, int midColor, int endColor, float translateX, float translateY){ 
    ObjectAnimator animateLeft = ObjectAnimator.ofFloat(mCurrentRect, "left", mCurrentRect.left, mCurrentRect.left-translateX); 
    ObjectAnimator animateRight = ObjectAnimator.ofFloat(mCurrentRect, "right", mCurrentRect.right, mCurrentRect.right+translateX); 
    ObjectAnimator animateTop = ObjectAnimator.ofFloat(mCurrentRect, "top", mCurrentRect.top, mCurrentRect.top-translateY); 
    ObjectAnimator animateBottom = ObjectAnimator.ofFloat(mCurrentRect, "bottom", mCurrentRect.bottom, mCurrentRect.bottom+translateY); 
    ArgbEvaluator evaluator = new ArgbEvaluator(); 
    ObjectAnimator animateColor = ObjectAnimator.ofObject(this, "color", evaluator, startColor,midColor,endColor); 
    animateBottom.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
     //TODO: DEBUG ANIMATOR 
     @Override 
     public void onAnimationUpdate(ValueAnimator valueAnimator) { 
      postInvalidate(); 
     } 
    }); 
    AnimatorSet rectAnimation = new AnimatorSet(); 
    rectAnimation.playTogether(animateLeft, animateRight, animateTop, animateBottom,animateColor); 
    rectAnimation.setDuration(1000).start(); 
    invalidate(); 


} 

playNote、playSound generateColorメソッド

//Generates color based on the press x and y. 
private int generateColor(float pressx, float pressy){ 
    int Red = (((int) (pressx%255)) << 16) & 0x00FF0000; //Shift red 16-bits and mask out other stuff 
    int Green = (((int) (pressy%255)) << 8) & 0x0000FF00; //Shift Green 8-bits and mask out other stuff 
    int Blue = ((int)((pressx+pressy)%255)) & 0x000000FF; //Mask out anything not blue. 

    return 0xFF000000 | Red | Green | Blue; //0xFF000000 for 100% Alpha. Bitwise OR everything together. 

} 

private void playSound(String noun){ 
    Resources res = context.getResources(); 
    int resID = res.getIdentifier(noun, "raw", context.getPackageName()); 
    MediaPlayer mediaPlayer = MediaPlayer.create(context,resID); 
    mediaPlayer.start(); 
    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
     @Override 
     public void onCompletion(MediaPlayer mediaPlayer) { 
      mediaPlayer.release(); 
     } 
    }); 
} 

private void playNote(float pressx, float pressy, String note){ 
    colorPaint=new Paint(); 
    colorPaint.setStyle(Paint.Style.STROKE); 
    colorPaint.setStrokeWidth(10); 
    colorPaint.setColor(generateColor(pressx,pressy)); 
    float translateX = 50.0f; 
    float translateY = 50.0f; 
    Random rand = new Random(10000); 
    int xr = rand.nextInt(); 
    int yr = rand.nextInt(); 
    int startColor = generateColor(pressx,pressy); 
    int midColor = generateColor(pressx+rand.nextInt(),pressy+rand.nextInt()); 
    int endColor = generateColor(pressx+xr,pressy+yr); 
    mCurrentRect = new AnimatableRectF(pressx-50,pressy-50,pressx+50,pressy+50); 
    debugx=pressx; 
    playAnimation(startColor,midColor,endColor, translateX, translateY); 
    playSound(note); 
} 

ありがとうございます!

+0

が見えます。 mCurrentRect = new AnimatableRectF(pressx-50、pressy-50、pressx + 50、pressy + 50); 描画が開始され、別のサウンドが再生されると、次のオブジェクト(onDraw()が再び呼び出される)の描画が開始されます。それはあなたが最後のものだけを見ている理由を説明することができます。 – WiseGuy

+0

しかし、rectリストを配列リストに格納してそれらから描画すると、すべての矩形を一度に描画するときに、最後まで描画されません。 onDraw自体がループ内で呼び出されることは決してないようです。なぜか、私はplayAnimationメソッドでinvalidate()を呼び出すため、なぜそうは思わないのでしょうか。 – JohnDoe

答えて

0

ビジー状態のwhileループを使用する代わりに、次のノートを再生する前に必要な時間を待ってください。 Timerまたはhandler.postDelayed(runnable, delayMilliseconds)、またはそれ以上の場合は、RxのObservable.timer()を使用します。

これは、ブロッキングループによってUIスレッドが実行されないため、画面が更新されないためです。あなたがマルチタスクを学習したくない場合は、最も簡単な方法は、実行することです:それぞれの音が法playNote()で再生された後、あなたのグローバルVaRのmCurrentRectをリセットされる可能性がありますように

Handler mainHandler = new Handler(context.getMainLooper()); 

mainHandler.postDelayed(new Runnable() { 
    public void run() { playNote(...) } 
}, Times.get(i)) 
+0

ありがとう!これは完全に機能しました。 – JohnDoe

関連する問題