You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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