package com.example.musicplayer.widget; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.util.AttributeSet; import android.view.View; import android.view.animation.AccelerateInterpolator; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.RelativeLayout; import com.example.musicplayer.R; import com.example.musicplayer.util.CommonUtil; import com.example.musicplayer.util.DisplayUtil; /** * Created by 残渊 on 2018/10/27. */ public class DiscView extends RelativeLayout { private ImageView mIvNeedle; private ObjectAnimator mNeedleAnimator; private ObjectAnimator mObjectAnimator; /*标记ViewPager是否处于偏移的状态*/ private boolean mViewPagerIsOffset = false; /*标记唱针复位后,是否需要重新偏移到唱片处*/ private boolean mIsNeed2StartPlayAnimator = false; private MusicStatus musicStatus = MusicStatus.STOP; public static final int DURATION_NEEDLE_ANIAMTOR = 500; private NeedleAnimatorStatus needleAnimatorStatus = NeedleAnimatorStatus.IN_FAR_END; private int mScreenWidth, mScreenHeight; /*唱针当前所处的状态*/ private enum NeedleAnimatorStatus { /*移动时:从唱盘往远处移动*/ TO_FAR_END, /*移动时:从远处往唱盘移动*/ TO_NEAR_END, /*静止时:离开唱盘*/ IN_FAR_END, /*静止时:贴近唱盘*/ IN_NEAR_END } /*音乐当前的状态:只有播放、暂停、停止三种*/ public enum MusicStatus { PLAY, PAUSE, STOP } public DiscView(Context context) { this(context, null); } public DiscView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DiscView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mScreenWidth = CommonUtil.getScreenWidth(context); mScreenHeight = CommonUtil.getScreenHeight(context); } @Override protected void onFinishInflate() { super.onFinishInflate(); initDiscImg(); initNeedle(); initObjectAnimator(); } private void initDiscImg() { ImageView mDiscBackground = findViewById(R.id.iv_disc_background); mObjectAnimator=getDiscObjectAnimator(mDiscBackground); mDiscBackground.setImageDrawable(getDiscDrawable( BitmapFactory.decodeResource(getResources(),R.drawable.default_disc) )); int marginTop = (int) (DisplayUtil.SCALE_DISC_MARGIN_TOP * mScreenHeight); LayoutParams layoutParams = (LayoutParams) mDiscBackground .getLayoutParams(); layoutParams.setMargins(0, marginTop, 0, 0); mDiscBackground.setLayoutParams(layoutParams); } private void initNeedle() { mIvNeedle = findViewById(R.id.iv_needle); int needleWidth = (int) (DisplayUtil.SCALE_NEEDLE_WIDTH * mScreenWidth); int needleHeight = (int) (DisplayUtil.SCALE_NEEDLE_HEIGHT * mScreenHeight); /*设置手柄的外边距为负数,让其隐藏一部分*/ int marginTop = (int) (DisplayUtil.SCALE_NEEDLE_MARGIN_TOP * mScreenHeight) * -1; int marginLeft = (int) (DisplayUtil.SCALE_NEEDLE_MARGIN_LEFT * mScreenWidth); Bitmap originBitmap = BitmapFactory.decodeResource(getResources(), R.drawable .ic_needle); Bitmap bitmap = Bitmap.createScaledBitmap(originBitmap, needleWidth, needleHeight, false); LayoutParams layoutParams = (LayoutParams) mIvNeedle.getLayoutParams(); layoutParams.setMargins(marginLeft, marginTop, 0, 0); int pivotX = (int) (DisplayUtil.SCALE_NEEDLE_PIVOT_X * mScreenWidth); int pivotY = (int) (DisplayUtil.SCALE_NEEDLE_PIVOT_Y * mScreenWidth); mIvNeedle.setPivotX(pivotX); mIvNeedle.setPivotY(pivotY); mIvNeedle.setRotation(DisplayUtil.ROTATION_INIT_NEEDLE); mIvNeedle.setImageBitmap(bitmap); mIvNeedle.setLayoutParams(layoutParams); } private void initObjectAnimator() { mNeedleAnimator = ObjectAnimator.ofFloat(mIvNeedle, View.ROTATION, DisplayUtil .ROTATION_INIT_NEEDLE, 0); mNeedleAnimator.setDuration(DURATION_NEEDLE_ANIAMTOR); mNeedleAnimator.setInterpolator(new AccelerateInterpolator()); mNeedleAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { /** * 根据动画开始前NeedleAnimatorStatus的状态, * 即可得出动画进行时NeedleAnimatorStatus的状态 * */ if (needleAnimatorStatus == NeedleAnimatorStatus.IN_FAR_END) { needleAnimatorStatus = NeedleAnimatorStatus.TO_NEAR_END; } else if (needleAnimatorStatus == NeedleAnimatorStatus.IN_NEAR_END) { needleAnimatorStatus = NeedleAnimatorStatus.TO_FAR_END; } } @Override public void onAnimationEnd(Animator animator) { if (needleAnimatorStatus == NeedleAnimatorStatus.TO_NEAR_END) { needleAnimatorStatus = NeedleAnimatorStatus.IN_NEAR_END; playDiscAnimator(); musicStatus = MusicStatus.PLAY; } else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_FAR_END) { needleAnimatorStatus = NeedleAnimatorStatus.IN_FAR_END; if (musicStatus == MusicStatus.STOP) { mIsNeed2StartPlayAnimator = true; } } if (mIsNeed2StartPlayAnimator) { mIsNeed2StartPlayAnimator = false; /** * 只有在ViewPager不处于偏移状态时,才开始唱盘旋转动画 * */ if (!mViewPagerIsOffset) { /*延时500ms*/ DiscView.this.postDelayed(new Runnable() { @Override public void run() { playAnimator(); } }, 50); } } } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); } /** * 得到唱盘图片 * 唱盘图片由空心圆盘及音乐专辑图片“合成”得到 */ public Drawable getDiscDrawable(Bitmap bitmap) { int discSize = (int) (mScreenWidth * DisplayUtil.SCALE_DISC_SIZE); int musicPicSize = (int) (mScreenWidth * DisplayUtil.SCALE_MUSIC_PIC_SIZE); Bitmap bitmapDisc = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R .drawable.ic_disc), discSize, discSize, false); Bitmap bitmapMusicPic = Bitmap.createScaledBitmap(bitmap, musicPicSize, musicPicSize, true); BitmapDrawable discDrawable = new BitmapDrawable(bitmapDisc); RoundedBitmapDrawable roundMusicDrawable = RoundedBitmapDrawableFactory.create (getResources(), bitmapMusicPic); //抗锯齿 discDrawable.setAntiAlias(true); roundMusicDrawable.setAntiAlias(true); Drawable[] drawables = new Drawable[2]; drawables[0] = roundMusicDrawable; drawables[1] = discDrawable; LayerDrawable layerDrawable = new LayerDrawable(drawables); int musicPicMargin = (int) ((DisplayUtil.SCALE_DISC_SIZE - DisplayUtil .SCALE_MUSIC_PIC_SIZE) * mScreenWidth / 2); //调整专辑图片的四周边距,让其显示在正中 layerDrawable.setLayerInset(0, musicPicMargin, musicPicMargin, musicPicMargin, musicPicMargin); return layerDrawable; } public ObjectAnimator getDiscObjectAnimator(ImageView disc) { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(disc, View.ROTATION, 0, 360); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.setDuration(30 * 1000); objectAnimator.setInterpolator(new LinearInterpolator()); return objectAnimator; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); } /*播放动画*/ private void playAnimator() { /*唱针处于远端时,直接播放动画*/ if (needleAnimatorStatus == NeedleAnimatorStatus.IN_FAR_END) { mNeedleAnimator.start(); } /*唱针处于往远端移动时,设置标记,等动画结束后再播放动画*/ else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_FAR_END) { mIsNeed2StartPlayAnimator = true; } } /*暂停动画*/ private void pauseAnimator() { /*播放时暂停动画*/ if (needleAnimatorStatus == NeedleAnimatorStatus.IN_NEAR_END) { pauseDiscAnimatior(); } /*唱针往唱盘移动时暂停动画*/ else if (needleAnimatorStatus == NeedleAnimatorStatus.TO_NEAR_END) { mNeedleAnimator.reverse(); /** * 若动画在没结束时执行reverse方法,则不会执行监听器的onStart方法,此时需要手动设置 * */ needleAnimatorStatus = NeedleAnimatorStatus.TO_FAR_END; } } /*播放唱盘动画*/ private void playDiscAnimator() { if (mObjectAnimator.isPaused()) { mObjectAnimator.resume(); } else { mObjectAnimator.start(); } } /*暂停唱盘动画*/ private void pauseDiscAnimatior() { mObjectAnimator.pause(); mNeedleAnimator.reverse(); } public void play() { playAnimator(); } public void pause() { musicStatus = MusicStatus.PAUSE; pauseAnimator(); } public void stop() { musicStatus = MusicStatus.STOP; pauseAnimator(); } public void next() { playAnimator(); selectMusicWithButton(); } public void last() { playAnimator(); selectMusicWithButton(); } public boolean isPlaying() { return musicStatus == MusicStatus.PLAY; } private void selectMusicWithButton() { if (musicStatus == MusicStatus.PLAY) { mIsNeed2StartPlayAnimator = true; pauseAnimator(); } else if (musicStatus == MusicStatus.PAUSE) { play(); } } }