版權聲明:本文爲博主原創文章,未經博主容許不得轉載java
系列教程:Android開發之從零開始系列android
源碼:本期內容比較簡單,源碼就直接在文中貼出來了canvas
你們要是看到有錯誤的地方或者有啥好的建議,歡迎留言評論api
前言:你們平時有用過MAKA或者易企秀這些H5模板製做工具嗎,不知道里面有個小細節你們有沒注意到,就是這個音樂小控件app
當咱們點擊這個控件時,它會開始旋轉並播放背景音樂,再次點擊時會重置回初始狀態。相似的旋轉效果在APP中也十分常見,例如一些音樂播放界面中不斷旋轉的音樂碟片ide
其效果會更復雜一些,碟片會隨着音樂的播放、暫停而旋轉或暫停在某個旋轉角度,從暫停恢復到播放時,又會從當前的角度開始不斷地旋轉。本期將教你們如何利用 屬性動畫 ObjectAnimator和 補間動畫 RotateAnimation 分別實現這一效果工具
本篇只着重於思路和實現步驟,裏面用到的一些知識原理不會很是細地拿來說,若是有不清楚的api或方法能夠在網上搜下相應的資料,確定有大神講得很是清楚的,我這就不獻醜了。本着認真負責的精神我會把相關知識的博文連接也貼出來(其實就是懶不想寫那麼多哈哈),你們能夠自行傳送。爲了照顧第一次閱讀系列博客的小夥伴,本篇有可能會出現一些在以前系列博客就講過的內容,看過的童鞋自行跳過該段便可oop
國際慣例,先上效果圖post
使用屬性動畫來實現這個效果是最簡單的,由於動畫的開始、暫停、結束和從新播放等方法系統都已經爲咱們封裝好了(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自己並無封裝暫停動畫的方法,因此實現起來會比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;//消費此長按事件,再也不向下傳遞
}
});
複製代碼
至此本篇教程到此結束,若是你們看了感受還不錯麻煩點個贊,大家的支持是我最大的動力~