2016-09-03 6 views
0

Androidでビューをアニメーション化するためにRxJavaを使用しようとしています。私は一定の間隔でビューのY位置を変更する必要がありますが、正しく機能していません。ここに私が始める機能があります:Androidのアニメーション用のRxJava

private void initiateCurrentWordFall(){ 
    txtFalling.setY(fallingWordStartY); 
    Observable<Long> observable = Observable.interval(100, TimeUnit.MILLISECONDS); 

    fallingSubs = observable 
      .subscribeOn(Schedulers.computation()) 
      .observeOn(Schedulers.computation()) 
      .subscribe(new Observer<Long>() { 

       @Override 
       public void onCompleted() { 

       } 

       @Override 
       public void onError(Throwable e) { 

       } 

       @Override 
       public void onNext(Long aLong) { 
        if(txtFalling.getY()!=screenHeight) { 
         txtFalling.setY(txtFalling.getY() + 1); 
         Log.d("Txt Y", String.valueOf(txtFalling.getY())); 
        } 
        else 
         wrongAnswerOrWordFeel(); 
       } 
      }); 
} 

私の実行では、画面の高さは1776です。

このコードは、0.1秒ごとにビューのYを1ピクセルずつ減らすことになっていました。私も何が起こってログインしようとすると、これは私が得るものです:

09-03 18:03:13.882 701-701/com.feliperrm.babbelproject D/Txt Y: -70.0 
09-03 18:03:13.890 701-701/com.feliperrm.babbelproject D/Txt Y: -69.0 
09-03 18:03:13.922 701-701/com.feliperrm.babbelproject D/Txt Y: -68.0 
09-03 18:03:13.923 701-701/com.feliperrm.babbelproject D/Txt Y: -67.0 
09-03 18:03:13.964 701-701/com.feliperrm.babbelproject D/Txt Y: -117.0 
09-03 18:03:13.974 701-701/com.feliperrm.babbelproject D/Txt Y: -116.0 
09-03 18:03:13.990 701-701/com.feliperrm.babbelproject D/Txt Y: -115.0 
09-03 18:03:14.021 701-701/com.feliperrm.babbelproject D/Txt Y: -114.0 
09-03 18:03:14.044 701-701/com.feliperrm.babbelproject D/Txt Y: -113.0 
09-03 18:03:14.058 701-701/com.feliperrm.babbelproject D/Txt Y: -112.0 

そしてこのbehaviousは(テキストビューがポイントになるとまで戻っ)全体にわたって繰り返されます。私は間違って何をしていますか?

EDIT:

が問題を見つけたが、私はまだそれが起こっている理由について興味があります。私は上記の投稿 この機能はRxJavaがTextViewの落下作っている間そのため、最初の行

txtFalling.setY(fallingWordStartY); 

はそれが再び上がるなり、複数回呼び出されています。しかし、なぜこの関数は何度も呼び出されていますか? これは私がそれを呼び出す場所である:私は他の終了後1を起動すると、それは非常に醜いことについて

txtCurrentWord.animate().setDuration(1000).setStartDelay(150).alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(new AccelerateInterpolator()) 
       .setListener(new AnimatorListenerAdapter() { 
        @Override 
        public void onAnimationEnd(Animator animation) { 
         super.onAnimationEnd(animation); 
         txtCurrentWord.animate() 
           .y(topWordY - txtCurrentWord.getHeight()/5) 
           .scaleX(0.6f).scaleY(0.6f).setInterpolator(new AccelerateDecelerateInterpolator()).setStartDelay(250).setDuration(750).start(); 
         bgNewWord.animate().alpha(0f).setStartDelay(250).setDuration(750) 
           .setListener(new AnimatorListenerAdapter() { 
            @Override 
            public void onAnimationEnd(Animator animation) { 
             super.onAnimationEnd(animation); 
             bgNewWord.setVisibility(View.GONE); 
             initiateCurrentWordFall(); 
            } 
           }).start(); 
        } 
       }).start(); 

申し訳ありませんが、ネストされたアニメーションがたくさんあります。私がそれらを再起動しなくても、onAnimationEndが複数回呼び出されているのを奇妙に思ってください!

+0

wrongAnswerOrWordFeel()とは何ですか? – jonathanrz

+0

プレイヤーから1つの人生を取り除くだけです。人生がすでにゼロであれば、ゲームを終了します。加入者またはオブザーバーに関連するものは何もありません。 –

+0

常に-67でリセットされますか? – jonathanrz

答えて

1

私はちょうど私自身の問題を発見しました。興味のある人には、アニメーションリスナーを設定したビューでアニメーションを開始していました。このリスナーはこのアニメーション設定中に設定されていなくても、まだ呼び出されていて、何度も繰り返し呼び出されるように設定されていました。私は、内側のtxtCurrentWordアニメーションに.setListener(null)を追加するだけでした。

0

RxJavaを使用してアニメーションを連鎖させようと思っていたときは、正しい軌道に乗っていたと思います。サンプルとして、アニメーションをObservableに変換するラッパーを作成しました。監視対象は、清掃を容易にするために、アニメーション化されているViewを返します。ボーナスとして、AnimationListenerは使用しません。この副作用は、アニメーションがキャンセルされた場合に通知を受け取らないことですが、必要ならば.withEndAction()をAnimationListenerに置き換えることができます。この基本的なイディオムは、ObjectAnimatorsなどの他のアニメーションタイプでも使用できます。

public class RxAnimation { 
    public static Observable<View> wrapViewPropertyAnimation(View view, Func1<View, ViewPropertyAnimator> animationCall) { 
     return Observable.<View>create(emitter -> { 
      ViewPropertyAnimator animation = 
        animationCall.call(view) 
        .withEndAction(() -> emitter.onNext(view)); 
      animation.start(); 
      emitter.setSubscription(new MainThreadSubscription() { 
       @Override 
       protected void onUnsubscribe() { 
        animation.cancel(); 
       } 
      }); 
     }, Emitter.BackpressureMode.BUFFER) 
       .subscribeOn(AndroidSchedulers.mainThread()); 
    } 

    public static void initiateCurrentWordFall() { 
     // Whatever this does... 
    } 

    public static void runSampleCode(View txtCurrentWord, View bgNewWord, int topWordY) { 
     wrapViewPropertyAnimation(txtCurrentWord, v -> 
       v.animate().setDuration(1000).setStartDelay(150) 
       .alpha(1f).scaleX(1f).scaleY(1f) 
       .setInterpolator(new AccelerateInterpolator())) 
       .switchMap(lastView -> wrapViewPropertyAnimation(lastView, v -> 
         v.animate().y(topWordY - txtCurrentWord.getHeight()/5) 
         .scaleX(0.6f).scaleY(0.6f) 
         .setInterpolator(new AccelerateDecelerateInterpolator()) 
         .setStartDelay(250).setDuration(750))) 
       .switchMap(lastView -> wrapViewPropertyAnimation(bgNewWord, v -> 
         v.animate().alpha(0f).setStartDelay(250).setDuration(750)) 
       ) 
       .doOnNext(lastView -> { 
        lastView.setVisibility(View.GONE); 
        initiateCurrentWordFall(); 
       }) 
       .observeOn(AndroidSchedulers.mainThread()) 
       // You should make sure your observable is bound to an Activity lifecycle 
       // to avoid leaks. I use RxLifecycle for this. 
       .subscribe(); 
    } 
} 
関連する問題