版權宣告:本文為博主原創文章,未經博主允許不得轉載
系列教程:Android開發之從零開始系列
原始碼:本期內容比較簡單,原始碼就直接在文中貼出來了
大家要是看到有錯誤的地方或者有啥好的建議,歡迎留言評論
前言:大家平時有用過MAKA或者易企秀這些H5模板製作工具嗎,不知道里面有個小細節大家有沒注意到,就是這個音樂小控制元件
當我們點選這個控制元件時,它會開始旋轉並播放背景音樂,再次點選時會重置回初始狀態。類似的旋轉效果在APP中也十分常見,例如一些音樂播放介面中不斷旋轉的音樂碟片
其效果會更復雜一些,碟片會隨著音樂的播放、暫停而旋轉或暫停在某個旋轉角度,從暫停恢復到播放時,又會從當前的角度開始不斷地旋轉。本期將教大家如何利用 屬性動畫 ObjectAnimator和 補間動畫 RotateAnimation 分別實現這一效果
本篇只著重於思路和實現步驟,裡面用到的一些知識原理不會非常細地拿來講,如果有不清楚的api或方法可以在網上搜下相應的資料,肯定有大神講得非常清楚的,我這就不獻醜了。本著認真負責的精神我會把相關知識的博文連結也貼出來(其實就是懶不想寫那麼多哈哈),大家可以自行傳送。為了照顧第一次閱讀系列部落格的小夥伴,本篇有可能會出現一些在之前系列部落格就講過的內容,看過的童鞋自行跳過該段即可
國際慣例,先上效果圖
用ObjectAnimator實現
使用屬性動畫來實現這個效果是最簡單的,因為動畫的開始、暫停、結束和重新播放等方法系統都已經為我們封裝好了(android 3.0以上開始支援),我們只需要繼承ImageView然後呼叫ObjectAnimator的相應方法即可,程式碼比較簡單,這裡就直接貼出來了
public class MusicButton extends AppCompatImageView {
private ObjectAnimator objectAnimator;
public static final int STATE_PLAYING =1;//正在播放
public static final int STATE_PAUSE =2;//暫停
public static final int STATE_STOP =3;//停止
public int state;
public MusicButton(Context context) {
super(context);
init();
}
public MusicButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MusicButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
state = STATE_STOP;
objectAnimator = ObjectAnimator.ofFloat(this, "rotation", 0f, 360f);//新增旋轉動畫,旋轉中心預設為控制元件中點
objectAnimator.setDuration(3000);//設定動畫時間
objectAnimator.setInterpolator(new LinearInterpolator());//動畫時間線性漸變
objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
}
public void playMusic(){
if(state == STATE_STOP){
objectAnimator.start();//動畫開始
state = STATE_PLAYING;
}else if(state == STATE_PAUSE){
objectAnimator.resume();//動畫重新開始
state = STATE_PLAYING;
}else if(state == STATE_PLAYING){
objectAnimator.pause();//動畫暫停
state = STATE_PAUSE;
}
}
public void stopMusic(){
objectAnimator.end();//動畫結束
state = STATE_STOP;
}
}
複製程式碼
效果如圖
用RotateAnimation實現
RotateAnimation本身並沒有封裝暫停動畫的方法,所以實現起來會比ObjectAnimator要複雜一些,本著學習研究的態度,沒有困難創造困難也要上,我們就來分析一下如何使用“原始的”RotateAnimation實現我們想要的效果
因為RotateAnimation動畫只有開始和結束的方法,所以當我們點選暫停按鈕時,需要記錄當前已經旋轉的角度,重繪View並將畫布旋轉之前記錄的角度。再次播放時,因為View的畫布已經旋轉至之前暫停的角度,我們只需要新建一個動畫從當前角度播放即可,具體程式碼如下
public class MusicButton extends AppCompatImageView {
public static final int STATE_PLAYING =1;//正在播放
public static final int STATE_PAUSE =2;//暫停
public static final int STATE_STOP =3;//停止
public int state;
private float angle;//記錄RotateAnimation中受插值器數值影響的角度
private float angle2;//主要用來記錄暫停時停留的角度,即View初始旋轉角度
private int viewWidth;
private int viewHeight;
private MusicAnim musicAnim;
public MusicButton(Context context) {
super(context);
init();
}
public MusicButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MusicButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
state = STATE_STOP;
angle = 0;
angle2 = 0;
viewWidth = 0;
viewHeight = 0;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewWidth = getMeasuredWidth();
viewHeight = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.rotate(angle2,viewWidth/2,viewHeight/2);
super.onDraw(canvas);
}
public class MusicAnim extends RotateAnimation{
public MusicAnim(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
super(fromDegrees, toDegrees, pivotX, pivotY);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
angle = interpolatedTime * 360;
}
}
public void playMusic(){
if(state == STATE_PLAYING){
angle2 = (angle2 + angle)%360;//可以取餘也可以不取,看實際的需求
musicAnim.cancel();
state = STATE_PAUSE;
invalidate();
}else {
musicAnim = new MusicAnim(0,360,viewWidth/2,viewHeight/2);
musicAnim.setDuration(3000);
musicAnim.setInterpolator(new LinearInterpolator());//動畫時間線性漸變
musicAnim.setRepeatCount(ObjectAnimator.INFINITE);
startAnimation(musicAnim);
state = STATE_PLAYING;
}
}
public void stopMusic(){
angle2 = 0;
clearAnimation();
state = STATE_STOP;
invalidate();
}
}
複製程式碼
MusicButton的程式碼寫完了,下面將按鈕結合音樂播放的程式碼貼出來,感興趣的小夥伴可以看看
mPlayer = MediaPlayer.create(this, R.raw.音樂名);
mPlayer.setLooping(true);
btnMusic = (MusicButton) findViewById(R.id.btn_music);
btnMusic.setOnClickListener(new View.OnClickListener() {//單擊播放或暫停
@Override
public void onClick(View v) {
btnMusic.playMusic();
try {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
btnMusic.setOnLongClickListener(new View.OnLongClickListener() {//長按停止
@Override
public boolean onLongClick(View v) {
try {
if (mPlayer != null) {
mPlayer.stop();
mPlayer.prepare();
}
} catch (Exception e) {
e.printStackTrace();
}
btnMusic.stopMusic();
return true;//消費此長按事件,不再向下傳遞
}
});
複製程式碼
至此本篇教程到此結束,如果大家看了感覺還不錯麻煩點個贊,你們的支援是我最大的動力~