Search code examples
androidmedia-playerimage-rotation

How to connect a rotating ImageView to MediaPlayer so that it rotates when MediaPlayer is playing in android


As in the title, I want to make a rotating disc which will rotate when I hit play on mediaplayer. Here is the code for my ImageView (for now it moves onTouch) :

public class DjDiscsHandler {
    public static double mCurrAngle = 0;
    public static double mPrevAngle = 0;

    public static void Discs(final ImageView djDisc, final String side) {
        djDisc.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final float xc = djDisc.getWidth() / 2;
                final float yc = djDisc.getHeight() / 2;

                final float x = event.getX();
                final float y = event.getY();

                switch(side) {
                    case "left":
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN: {
                            mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
                            break;
                        }
                        case MotionEvent.ACTION_MOVE: {
                            mPrevAngle = mCurrAngle;
                            mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
                            Log.i("Current Angle", "" + mCurrAngle);
                            animate(mPrevAngle, mCurrAngle, 0, djDisc);
                            break;
                        }
                        case MotionEvent.ACTION_UP: {
                            mPrevAngle = mCurrAngle = 0;
                            break;
                        }
                    }
                        break;
                    case "right":
                        switch (event.getAction()) {
                            case MotionEvent.ACTION_DOWN: {
                                mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
                                break;
                            }
                            case MotionEvent.ACTION_MOVE: {
                                mPrevAngle = mCurrAngle;
                                mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
                                animate(mPrevAngle, mCurrAngle, 0, djDisc);
                                break;
                            }
                            case MotionEvent.ACTION_UP: {
                                mPrevAngle = mCurrAngle = 0;
                                break;
                            }
                        }
                        break;
                }

                return true;
            }
        });
    }

    public static void animate(double fromDegrees, double toDegrees, long durationMillis, final ImageView djDiscLeft) {
        final RotateAnimation rotate = new RotateAnimation((float) fromDegrees, (float) toDegrees,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(durationMillis);
        rotate.setFillEnabled(true);
        rotate.setFillAfter(true);
        djDiscLeft.startAnimation(rotate);
    }
}

I found the code for this here: How can i use RotateAnimation to rotate a circle?

Now I want to add it to my mediaplyer handler:

            play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Deck.mediaplayerReadyLeft) {
                    Deck.mediaplayerLeft.start();
                    double mCurrAngle = 0;
                    while(Deck.mediaplayerLeft.isPlaying()) {
                        DjDiscsHandler.animate(mCurrAngle, mCurrAngle + 1, 0, Deck.djDiscLeft);
                        mCurrAngle++;
                    }
                }
            }
        });

Unfortunately the program freezes when I press play and crushes a few moments later.

Any suggestions?


Solution

  • Your issue is that you are entering a while() loop which is halting the rest of your app while it processes. Remember, you're not on a separate thread here, so while the code in your while() loop executes, nothing else is. You're essentially trying to do a makeshift "draw" loop to perform the animation, but you can't just stop everything else to perform that one action. Instead, you would want to trigger an animation to start when the play button is pressed. Try this instead...

    In your anim folder inside your res folder, add this rotate anim xml file...

    <?xml version="1.0" encoding="utf-8"?>
    <rotate
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:interpolator="@android:anim/linear_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite"
        android:repeatMode="restart"
        android:toDegrees="360" />
    

    Then when it comes time to start the animation (i.e., when you hit the play button), you would execute something like this...

    Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate_anim);
    ImageView yourImageView = (ImageView) findViewById(R.id.your_image_view);
    yourImageView.startAnimation(rotateAnimation);
    

    To stop the rotation animation, you can just call clearAnimation() on your ImageView.

    Hope this helps!