升级版音乐播放器
来源:互联网 发布:程序员面试问题及答案 编辑:程序博客网 时间:2024/05/22 04:31
每天写个APP_第2
天——升级版音乐播放器
:有同学说我写的不够详细,我以后会注意和完善。又说能否有源码,我一般会在文章里贴出所有源码,另外我今天会吧代码传到github上提供下载。
回顾
:上篇文章实现各一个简单的播放器,但是仍然不是很酷。今天,我们对它做个改进。还记得网易云音乐
APP中播放界面有个CD
吗?当播放音乐时,中间的CD就会转动,是不是很酷?今天我们也把中间的CD转起来!然后,我们还要添加歌曲进度条,还可以用手指拖动进度条实现歌曲的指定播放位置。
- 实现CD唱片的转动!
- 添加歌曲进度条
- SeekBar类
- Runnable类
- Animation类
- xml:rotate
界面
转动吧!CD
Android 平台提供了两类动画,一类是 Tween 动画,即通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果;第二类是 Frame 动画,即顺序播放事先做好的图像,跟电影类似。这里我们使用 Tween动画的rotate实现旋转效果。
rotate.xml
在res文件夹新建anim文件夹,在里面新建rotae.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:fromDegrees="0" android:toDegrees="359" android:pivotX="50%" android:pivotY="50%" android:repeatCount="-1" android:duration="4500" /></set>
解析:从0到359度开始循环旋转,0-359(若设置成360在停止时会出现停顿现象)度旋转所用时间为500ms,旋转中心距离view的左顶点为50%距离,距离view的上边缘为50%距离,即正中心,具体每个含义见下面的具体属性介绍。
android:fromDegrees
起始的角度度数
android:toDegrees
结束的角度度数,负数表示逆时针,正数表示顺时针。如10圈则比android:fromDegrees大3600即可
android:pivotX
旋转中心的X坐标
浮点数或是百分比。浮点数表示相对于Object的左边缘,如5; 百分比表示相对于Object的左边缘,如5%; 另一种百分比表示相对于父容器的左边缘,如5%p; 一般设置为50%表示在Object中心
android:pivotY
旋转中心的Y坐标
浮点数或是百分比。浮点数表示相对于Object的上边缘,如5; 百分比表示相对于Object的上边缘,如5%; 另一种百分比表示相对于父容器的上边缘,如5%p; 一般设置为50%表示在Object中心
android:duration
表示从android:fromDegrees转动到android:toDegrees所花费的时间,单位为毫秒。可以用来计算速度。
android:interpolator
表示变化率,但不是运行速度。一个插补属性,可以将动画效果设置为加速,减速,反复,反弹等。默认为开始和结束慢中间快,
android:startOffset
在调用start函数之后等待开始运行的时间,单位为毫秒,若为10,表示10ms后开始运行
android:repeatCount
重复的次数,默认为0,必须是int,可以为-1表示不停止
android:repeatMode
重复的模式,默认为restart,即重头开始重新运行,可以为
reverse即从结束开始向前重新运行。在android:repeatCount大于0或为infinite时生效
android:detachWallpaper
表示是否在壁纸上运行
android:zAdjustment
表示被animated的内容在运行时在z轴上的位置,默认为
normal。
normal
保持内容当前的z轴顺序
top
运行时在最顶层显示
bottom
运行时在最底层显示
具体参考我转载的文章:点击进入 哪里用的到
:没见过刷新转圈的动画吗
在java里调用
animation=AnimationUtils.loadAnimation(this, R.anim.rotate); //设置匀速LinearInterpolator linearInterpolator=new LinearInterpolator();animation.setInterpolator(linearInterpolator);
SeekBar!
音乐播放是MediaPlayer这个类控制的,进度条SeekBar可以用来显示播放进度,用户也可以利用SeekBar的滑块来控制音乐的播放。两个按钮一个用来播放歌曲启动线程,另一个取消线程和停止播放歌曲。
SeekBar
:
设置滑块的位置方法为:setProgress(int value)
;
设置最大值的方法为:setMax(int value);
MusicPlayer:
播放音乐方法为:start();
停止音乐播放的方法为:stop();
控制音乐播放位置为:seekTo(int value);
获得音乐长度为:getDuration();
获得现在播放的位置:getCurrentPosition();
Handler:
启动线程:post(Runnable runnable);
取消线程:removeCallbacks(Runnable runnable);
延迟启动线程(time 单位为毫秒):postDelayed(Runnable, int time);
MainActivity.java
本代码较于上篇的代码,针OOP思想做了些改善。注意SeekBar监听器的代码,你想写个老式卡带播放机子或是留声机吗?看看吧!
package com.example.playerofmusic;import android.app.Activity;import android.media.MediaPlayer;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.Window;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.view.animation.LinearInterpolator;import android.view.animation.RotateAnimation;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.TextView;import java.io.IOException;import java.util.Timer;import java.util.TimerTask;import com.example.playerofmusic.R.anim;public class MainActivity extends Activity { private ImageView songImage; private TextView songText; private Button songStart; private Button songStop; private Button songPause; private EditText editSongName; private MediaPlayer musicPlayer; //----------------以下是新添代码---------- private Handler handler; private SeekBar songSeekBar; private Animation animation;//使用动画类 private Runnable seekBarThread; //------------------------------------ /* * 也可用Timer类和TimerTask类实现SeekBar的持续移动 */ /*private Timer mTimer; private TimerTask mTimerTask; private boolean isChanging;*/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* * //设置为NoTitle,没有标题栏,上篇在清单文件中,添加的 * theme属性。 */ requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); findView();//绑定控件 setListener(); SongImageAnim(); musicPlayer= new MediaPlayer();//实例化MediaPlayer handleSongImageAnim(); songSeekBarProgress();//开启线子程控制seekbar跟随歌曲的进度 } private void songSeekBarProgress() { // TODO Auto-generated method stub seekBarThread=new Runnable() { @Override public void run() { // TODO Auto-generated method stub //10毫秒执行以下线程,目的是持续改变SeekBar的位置 songSeekBar.setProgress(musicPlayer.getCurrentPosition()); handler.postDelayed(seekBarThread, 10); } }; } private void handleSongImageAnim() { // TODO Auto-generated method stub //用handler来处理图片的旋转 handler=new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); if(msg.what==1){//姑且设what为1 if(animation!=null&&musicPlayer.isPlaying()){ songImage.startAnimation(animation); } }else{ if(animation!=null){ songImage.clearAnimation(); } } } }; } private void SongImageAnim() { // TODO Auto-generated method stub animation=AnimationUtils.loadAnimation(this, R.anim.rotate); //设置匀速 LinearInterpolator linearInterpolator=new LinearInterpolator(); animation.setInterpolator(linearInterpolator); } private void setListener() { // TODO Auto-generated method stub //为三个按钮设置监听器 songPause.setOnClickListener(new ButtonListener()); songStop.setOnClickListener(new ButtonListener()); songStart.setOnClickListener(new ButtonListener()); songSeekBar.setOnSeekBarChangeListener(new SongSeekBarListener()); } private void findView() { // TODO Auto-generated method stub songImage=(ImageView)findViewById(R.id.image_songImage); songText=(TextView)findViewById(R.id.text_songName); editSongName=(EditText)findViewById(R.id.edit_songName); songSeekBar=(SeekBar) findViewById(R.id.seekBar_song); songStart=(Button)findViewById(R.id.button_start); songStop=(Button)findViewById(R.id.button_stop); songPause=(Button)findViewById(R.id.button_pause); } private class ButtonListener implements View.OnClickListener{ @Override public void onClick(View view) { try{//这里需要处理异常 switch (view.getId()){ case R.id.button_start: //文件名 String fileName=editSongName.getText().toString(); songText.setText(fileName); //恢复原始界面 if(songPause.getText().equals("继续")){ songPause.setText("暂停"); } //重置 musicPlayer.reset(); //文件路径 musicPlayer.setDataSource("/sdcard/netease/cloudmusic/Music/"+fileName+".mp3"); musicPlayer.prepare(); musicPlayer.start(); handler.sendEmptyMessage(1); songSeekBar.setMax(musicPlayer.getDuration());//设置进度条 handler.post(seekBarThread); /*mTimer = new Timer(); mTimerTask = new TimerTask() { @Override public void run() { if(isChanging==true) { return; } songSeekBar.setProgress(musicPlayer.getCurrentPosition()); } }; mTimer.schedule(mTimerTask, 0, 10); */ break; case R.id.button_stop: musicPlayer.stop(); songPause.setText("暂停"); handler.sendEmptyMessage(2);// songSeekBar.setProgress(0); handler.removeCallbacks(seekBarThread); break; case R.id.button_pause: //注意界面的更改 if(musicPlayer.isPlaying()){ musicPlayer.pause(); ((Button)view).setText("继续"); handler.sendEmptyMessage(2); handler.post(seekBarThread); }else{ musicPlayer.start(); handler.sendEmptyMessage(1); ((Button)view).setText("暂停"); } break; } }catch (IOException e){ e.printStackTrace(); } } } class SongSeekBarListener implements OnSeekBarChangeListener{ @Override public void onProgressChanged(android.widget.SeekBar arg0, int progress, boolean fromUser) { // TODO Auto-generated method stub if(fromUser==true){ if(musicPlayer.isPlaying()) musicPlayer.pause(); musicPlayer.seekTo(progress); //如果在这里start(),效果就像老式卡带机或是留声机,不信你试试 //musicPlayer.start(); } } @Override public void onStartTrackingTouch(android.widget.SeekBar arg0) { // TODO Auto-generated method stub //isChanging=true; } @Override public void onStopTrackingTouch(android.widget.SeekBar arg0) { // TODO Auto-generated method stub //musicPlayer.seekTo(songSeekBar.getProgress()); //isChanging=false; //当手指抬起时,开始从歌曲新的位置播放歌曲 if(!musicPlayer.isPlaying()) musicPlayer.start(); } } @Override protected void onPause() { super.onPause(); if(musicPlayer!=null){ if(musicPlayer.isPlaying()) musicPlayer.stop(); } } @Override protected void onResume() { super.onResume(); if(musicPlayer!=null){ if(musicPlayer.isPlaying()) musicPlayer.start(); } } @Override protected void onDestroy() { super.onDestroy(); if(musicPlayer!=null){ if(musicPlayer.isPlaying()) musicPlayer.stop(); musicPlayer.release(); } if(animation!=null){ songImage.clearAnimation(); } handler.removeCallbacks(seekBarThread); }}
界面xml
做了一些小改动。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff646469" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="1"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingTop="15dp" android:textSize="35sp" android:textColor="#fff" android:text="音乐播放器"/> <TextView android:layout_marginTop="22dp" android:id="@+id/text_songName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:textColor="#fff" android:textSize="19sp" android:text="好妹妹"/> <ImageView android:layout_marginTop="18dp" android:id="@+id/image_songImage" android:layout_width="290dp" android:layout_height="290dp" android:layout_gravity="center" android:src="@drawable/ico2"/> <SeekBar android:layout_marginTop="20dp" android:id="@+id/seekBar_song" android:max="100" android:layout_width="300dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"/> <EditText android:layout_gravity="center" android:id="@+id/edit_songName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="输入歌曲名"/> <LinearLayout android:layout_marginTop="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/button_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3.333" android:textColor="#fff" android:text="暂停"/> <Button android:id="@+id/button_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3.333" android:textColor="#fff" android:text="播放"/> <Button android:id="@+id/button_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3.333" android:textColor="#fff" android:text="停止"/> </LinearLayout> </LinearLayout></RelativeLayout>
明天的APP
明天继续完善这个音乐播放器,1.美化按钮2.播放网络上的音乐
- 升级版音乐播放器
- WPF做的小型音乐播放器-升级版
- Qt版音乐播放器
- 服务版音乐播放器
- android音乐播放器播放音乐卡
- Android 音乐播放 类似音乐播放器
- [PhoneGap]音乐播放器Android版
- android音乐播放器(改进版)
- android音乐播放器(改进版)
- 音乐播放器 c语言版加强版
- 音乐播放器的实现(简易版)
- MFC版的音乐播放器
- H5,Audio音乐播放器(移动版)
- vbs版的音乐播放器
- 畅想音乐播放器第二版
- swift版QQ音乐播放器(一)
- swift版QQ音乐播放器(二)
- 音乐播放器(iOS简单版)
- android 无线调试
- ireport的使用
- C++之"类模板与STL编程"
- Majority Number II——算法练习
- 学Python这本书不错!
- 升级版音乐播放器
- android 内存相关
- wince地址映射过程
- markdown
- 20150213 N1
- CodeForces 69D Dot
- Linux 平台误删 home oracle 根目录的解决方法
- 游戏程序员养成计划
- print,random整理