UI界面模仿QQ音乐
实现一个简单的本地播放器,功能包括:播放,暂停,上一曲,下一曲,进度条。
读取本地音乐
1.创建一个Song类
public class Song {
public String song;//歌曲名
public String singer;//歌手
public long size;//歌曲所占空间大小
public int duration;//歌曲时间长度
public String path;//歌曲地址
public String album;//专辑名
}
2.用于获取本地音乐的Utils
public class Utils {
//定义一个集合,存放从本地读取到的内容
public static List list;
public static Song song;
public static List getmusic(Context context) {
list = new ArrayList<>();
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null, null, null, MediaStore.Audio.AudioColumns.IS_MUSIC);
if (cursor != null) {
while (cursor.moveToNext()) {
song = new Song();
song.song = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
song.album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM));
song.singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
song.path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
song.duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
song.size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
//把歌曲名字和歌手切割开
if (song.size > 1000 * 800) {
if (song.song.contains("-")) {
String[] str = song.song.split("-");
song.singer = str[0];
song.song = str[1];
}
list.add(song);
}
}
}
cursor.close();
return list;
}
// 转换歌曲时间的格式
public static String formatTime(int time) {
if (time / 1000 % 60 < 10) {
String tt = time / 1000 / 60 + ":0" + time / 1000 % 60;
return tt;
} else {
String tt = time / 1000 / 60 + ":" + time / 1000 % 60;
return tt;
}
}
}
3.在布局里面定义一个ListView,并写一个适配器
//适配器
class MyAdapter extends BaseAdapter {
Context context;
List list;
private int mSelect; //选中项
public MyAdapter(MainActivity mainActivity, List list) {
this.context = mainActivity;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
Myholder myholder;
if (view == null) {
myholder = new Myholder();
view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.text, null);
// myholder.t_position = view.findViewById(R.id.t_postion);
myholder.t_song = view.findViewById(R.id.t_song);
myholder.t_singer = view.findViewById(R.id.t_singer);
myholder.t_blank=view.findViewById(R.id.t_blank);
myholder.t_albumn=view.findViewById(R.id.t_albumn);
myholder.t_point=view.findViewById(R.id.t_point);
myholder.t_duration = view.findViewById(R.id.t_duration);
view.setTag(myholder);
} else {
myholder = (Myholder) view.getTag();
}
myholder.t_song.setText(list.get(i).song.toString());
myholder.t_singer.setText(list.get(i).singer.toString());
String time = Utils.formatTime(list.get(i).duration);
myholder.t_albumn.setText(list.get(i).album.toString());
myholder.t_duration.setText(time);
//myholder.t_position.setText(i + 1 + "");
//设置相关数据
if (mSelect==-1){
myholder.t_song.setEnabled(true);
myholder.t_singer.setEnabled(true);
myholder.t_blank.setVisibility(View.INVISIBLE);
//选中项背景
myholder.t_song.setTextColor(getResources().getColor(R.color.tilte_color));
myholder.t_singer.setTextColor(getResources().getColor(R.color.tilte_color));
myholder.t_albumn.setTextColor(getResources().getColor(R.color.tilte_color));
myholder.t_point.setTextColor(getResources().getColor(R.color.tilte_color));
}
if (mSelect == i) {
myholder.t_song.setEnabled(true);
myholder.t_singer.setEnabled(true);
myholder.t_blank.setVisibility(View.VISIBLE);
//选中项背景
myholder.t_song.setTextColor(getResources().getColor(R.color.theme));
myholder.t_singer.setTextColor(getResources().getColor(R.color.theme));
myholder.t_albumn.setTextColor(getResources().getColor(R.color.theme));
myholder.t_point.setTextColor(getResources().getColor(R.color.theme));
myholder.t_duration.setTextColor(getResources().getColor(R.color.theme));
} else {
myholder.t_song.setEnabled(false);
myholder.t_singer.setEnabled(false);
myholder.t_blank.setVisibility(View.INVISIBLE);
//其他项背景
myholder.t_song.setTextColor(getResources().getColor(R.color.tilte_color));
myholder.t_singer.setTextColor(getResources().getColor(R.color.song));
myholder.t_albumn.setTextColor(getResources().getColor(R.color.song));
myholder.t_point.setTextColor(getResources().getColor(R.color.song));
myholder.t_duration.setTextColor(getResources().getColor(R.color.song));
}
return view;
}
class Myholder {
ImageView t_blank;
TextView t_position, t_song, t_singer, t_duration,t_albumn,t_point;
}
//刷新方法
public void changeSelected(int positon){
if (positon != mSelect) {
mSelect = positon;
notifyDataSetChanged();
}
}
}
在类里面定义一个刷新位置的方法changeSelectde与ListView的点击监听事件配合使用,用于ListView被点击后将position参数传入,相应的文字颜色的改变
4.给ListView设置适配器
mylist = (ListView) findViewById(R.id.mylist);
list = new ArrayList<>();
list = Utils.getmusic(this);//获取音乐
myAdapter = new MyAdapter(this, list);
mylist.setAdapter(myAdapter);
5.使用MediaPlayer播放音乐
把音乐读取到ListView之后,点击音乐列表的音乐,就能够进行音乐的播放,并在底栏显示相应的音乐名,歌手名,可以拖动进度条进行音乐的控制,点击相应的按钮能够暂停,上一曲,下一曲。
首先封装一个播放音乐的方法,传入的参数currentPosition为音乐的位置
private void musicPlay(int currentPosition) {
seekBar.setMax(list.get(currentPosition).getDuration());
try {
// 重置音频文件,防止多次点击会报错
mediaPlayer.reset();
//调用方法传进播放地址
mediaPlayer.setDataSource(list.get(currentPosition).getPath());
//异步准备资源,防止卡顿
mediaPlayer.prepareAsync();
//调用音频的监听方法,音频准备完毕后响应该方法进行音乐播放
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();//开始播放
Thread thread = new Thread(new SeekBarThread());//更新SeekBar的线程
thread.start();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
然后为ListView设置点击事件
mylist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
currentPosition=position;
musicPlay(currentPosition);//播放音乐
myAdapter.changeSelected(currentPosition);//设置字体变色
play.setVisibility(View.INVISIBLE);//播放按钮消失
pause.setVisibility(View.VISIBLE);//暂停按钮出现
String song=list.get(currentPosition).song;//获取音乐名
String singer=list.get(currentPosition).singer;//获取歌手名
bottomSong.setText(song);//底栏显示音乐名
bottomSinger.setText(singer);//底栏显示歌手名
gang.setVisibility(View.VISIBLE);//横杠
}
});
播放,暂停,上一曲,下一曲按钮点击事件
//暂停按钮
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPlayer.pause();//暂停音乐
pause.setVisibility(View.INVISIBLE);
play.setVisibility(View.VISIBLE);
}
});
//播放按钮
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
play.setVisibility(View.INVISIBLE);
pause.setVisibility(View.VISIBLE);
mediaPlayer.start();//播放音乐
}
});
/**
* 下一曲
*/
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentPosition++;
if (currentPosition > list.size() - 1) {
currentPosition = 0;
}
musicPlay(currentPosition);
myAdapter.changeSelected(currentPosition);//ListView颜色变化
//底栏设置正在播放的歌曲信息
String song=list.get(currentPosition).song;
String singer=list.get(currentPosition).singer;
bottomSong.setText(song);
bottomSinger.setText(singer);
gang.setVisibility(View.VISIBLE);
}
});
/**
* 上一曲
*/
pre.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentPosition--;
if (currentPosition < 0) {
currentPosition = list.size() - 1;
}
musicPlay(currentPosition);
myAdapter.changeSelected(currentPosition);//ListView颜色变化
//底栏设置正在播放的歌曲信息
String song=list.get(currentPosition).song;
String singer=list.get(currentPosition).singer;
bottomSong.setText(song);
bottomSinger.setText(singer);
gang.setVisibility(View.VISIBLE);
}
});
给mediaPlayer添加一个监听事件,实现当前音乐播放完成后自动播放下一首的功能
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
currentPosition++;
if (currentPosition > list.size() - 1) {
currentPosition = 0;
}
musicPlay(currentPosition);
myAdapter.changeSelected(currentPosition);
//底栏设置正在播放的歌曲信息
String song=list.get(currentPosition).song;
String singer=list.get(currentPosition).singer;
bottomSong.setText(song);
bottomSinger.setText(singer);
gang.setVisibility(View.VISIBLE);
}
});
5.进度条
使用Handler类,进行SeekBar的更新
private static final int UPDATE_SEEKBAR=0;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case UPDATE_SEEKBAR:
// 将SeekBar位置设置到当前播放位置
seekBar.setProgress(mediaPlayer.getCurrentPosition());
break;
default:
break;
}
}
};
定义一个类,实现Runnable接口进行SeekBar状态的刷新
class SeekBarThread implements Runnable {
@Override
public void run() {
while (mediaPlayer.isPlaying()) {
try {
// 每500毫秒更新一次位置
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message=new Message();
message.what=UPDATE_SEEKBAR;
handler.sendMessage(message);
}
}
}
给SeekBar添加监听事件,实现拖动进度条改变音乐进度
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser==true){
mediaPlayer.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
源码下载链接:
下载链接