AndroidStudio 简单却功能完备的音乐播放器 您所在的位置:网站首页 功能歌曲 AndroidStudio 简单却功能完备的音乐播放器

AndroidStudio 简单却功能完备的音乐播放器

2024-07-03 07:55| 来源: 网络整理| 查看: 265

音乐播放器 前言总体设计详细设计扫描功能歌曲列表功能播放控制功能播放历史功能歌单操作功能搜索功能精化设计侧边栏功能 界面展示参考资料项目链接

前言

课设设计作品,参考了网上很多资料和实例,整了一个功能齐全的播放器 发上来供大家借鉴学习,如果大家能继续改进就再好不过了。 实验目的:

学会如何使用 MediaPlayer 等媒体播放组件。学会如何进行数据保存。 总体设计

设计介绍: 综合运用UI界面设计、数据存储、Activity(活动)、Service(服务)、MediaPlayer、ListView、RecyclerView等知识,设计开发一款具有音乐列表的音乐播放器。 设计步骤: 在这里插入图片描述

音乐播放器功能模块:

播放列表:能够读取手机中的音频文件,建立播放列表。播放控制:能够对播放进行控制,能够开始/继续播放、暂停播放、上一 首、下一首、单曲循环、列表播放,并能根据进度条自由选择播放进度。播放历史:能够存储已播放过的历史,并能够清空历史。歌单操作:能够在歌单页面建立额外的自定义歌单,并能够选择歌曲添加其中,并能够移除歌曲,删除歌单。侧边栏:作为拓展辅助功能,方便操作,方便以后扩充。搜索栏:根据所在页面,能够在搜索栏搜索需要的对象。 详细设计

程序流程: 在这里插入图片描述

扫描功能

歌曲JavaBean数据库文件Song.java,主要存储数据如下

public class Song implements Serializable {//javabean数据库 public String id; //歌曲id public String song; //歌曲名称 public String singer; //歌手名称 public String album; //专辑名称 public long duration; //歌曲时长 public String path; //歌曲路径 public long size;//大小

扫描本地歌曲对应文件:MusicUtils.java

public class MusicUtils { // 扫描系统里面的音频文件,返回一个list集合 public static List getMusicData(Context context) { List list = new ArrayList(); // 查询曲库 //Cursor 提供遍历查询结果的方法//getcontentresolver访问数据// Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null,null, MediaStore.Audio.AudioColumns.IS_MUSIC); int id=-1; if (cursor != null) {//查询结果非空 { while (cursor.moveToNext()) {//循环查询数据库 Song song = new Song();//获取相应的属性值 song.duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)); song.size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)); if (song.duration>30*1000&&song.size > 1000 * 800) { song.song = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)); //获取列,getColumnIndexOrThrow如果没找到该列名,会抛出IllegalArgumentExceptio异常 song.singer = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); song.path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)); song.album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //获取相应的的属性值 if (song.song.contains(".mp3")) { //分离文件格式后缀 String[] str = song.song.split(".mp3"); song.song = str[0]; } if (song.song.contains(".ogg")) {//分离文件格式后缀 String[] str = song.song.split(".ogg"); song.song = str[0]; } if (song.song.contains(".flav")) {//分离文件格式后缀 String[] str = song.song.split(".flav"); song.song = str[0]; } //分离后缀 if (song.song.contains("-")) {//用-分离歌名和歌手 String[] str = song.song.split("-"); song.singer = str[0]; song.song = str[1]; } ++id; String sid = String.valueOf(id+1); song.id=sid; list.add(song);//添加到表中 } } cursor.close();// 释放资源 } return list; } 歌曲列表功能

音频数据适配器MyAdapter.java,将扫描到的音频文件进行数据适配,关键代码:

public void onBindViewHolder(@NonNull LocalMusicViewHolder holder, final int position) { Song musicBean = mDatas.get(position); if (musicBean != null) {//非空判断,防止报错 holder.idTv.setText(musicBean.getId()); holder.songTv.setText(musicBean.getSong()); holder.singerTv.setText(musicBean.getSinger()); holder.albumTv.setText(musicBean.getAlbum()); //转换时间格式 SimpleDateFormat sdf = new SimpleDateFormat("mm:ss"); String time = sdf.format(new Date(musicBean.getDuration())); holder.timeTv.setText(time); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.OnItemClick(v, position); } }); } } class LocalMusicViewHolder extends RecyclerView.ViewHolder{ TextView idTv,songTv,singerTv,albumTv,timeTv; public LocalMusicViewHolder(View itemView) { super(itemView); idTv = itemView.findViewById(R.id.music_num);//id songTv = itemView.findViewById(R.id.music_song);//歌名 singerTv = itemView.findViewById(R.id.music_singer);//歌手 albumTv = itemView.findViewById(R.id.music_album);//专辑 timeTv = itemView.findViewById(R.id.music_duration);//时长 } }

其中的id对应布局文件item_song.xml中的控件,布局效果如下 在这里插入图片描述 在MusicListActivity(歌曲列表Activity)初始化控件后再初始化数据。 初始化数据函数initData():

public static List list; list = new ArrayList();//歌单数组 list.addAll(sheet.getList()); adapter = new MyAdapter(this,list);// 创建适配器对象 musicRv.setAdapter(adapter); //musicRV为对应布局文件activity_music_list.xml中的RecyclerView控件的id //设置布局管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); musicRv.setLayoutManager(layoutManager); adapter.notifyDataSetChanged(); 播放控制功能

服务类:MusicService.java 包含与播放有关的函数,关键代码:

public class MyBinder extends Binder { public boolean setDatas(List musicBeans){//获取歌曲列表list Log.d("MusicService----0----", "setDatas"); mDatas = musicBeans; musicDataSize = mDatas.size(); return true; } public void setMusic(int Id){ Log.d("MusicService----1----", "setMusic"); //重置播放 mediaPlayer.reset(); //进度记录清零 pausePosition=0; //设置新的音乐 music_Id=Id; Song musicBean = mDatas.get(music_Id); try { //设置信息 path = musicBean.getPath(); mediaPlayer.setDataSource(path); music_song = musicBean.getSong(); music_singer = musicBean.getSinger(); music_duration = (int) musicBean.getDuration(); // music_num=musicBean.getNum(); //调用意图服务,更新activity内容 Intent intentInfo = new Intent("com.example.musicapplication.intentService"); intentInfo.setPackage(getPackageName()); intentInfo.putExtra("music_id", music_Id); intentInfo.putExtra("music_song", music_song); intentInfo.putExtra("music_singer", music_singer); intentInfo.putExtra("music_duration", music_duration); // intentInfo.putExtra("music_duration", music_num); startService(intentInfo); myBinder.playMusic(); } catch (IOException e) { e.printStackTrace(); } } public void playMusic() { /* 播放音乐的函数*/ Log.d("MusicService----2----", "playMusic"); if (mediaPlayer != null && !mediaPlayer.isPlaying()) { if (pausePosition == 0) { try { mediaPlayer.prepare(); mediaPlayer.start(); playState=false; } catch (IOException e) { e.printStackTrace()} } else { //从暂停到播放 mediaPlayer.seekTo(pausePosition); mediaPlayer.start(); playState=false; } } } public void pauseMusic() { /* 暂停音乐的函数*/ Log.d("MusicService----3----", "pauseMusic"); if (mediaPlayer != null && mediaPlayer.isPlaying()) { pausePosition = mediaPlayer.getCurrentPosition(); mediaPlayer.pause(); } } public void play_next() { //判断是否为单曲循环 if(!playModule) { //判断是否是最后一首 if (music_Id >= musicDataSize - 1) { //从第一首开始播放 music_Id = -1; } music_Id = music_Id + 1; } setMusic(music_Id); playMusic(); playState=false; } public void play_last() { music_Id = music_Id-1; if(music_Id==-1) return; setMusic(music_Id); playMusic(); } public void stopMusic() { /* 停止音乐的函数*/ Log.d("MusicService----4----", "stopMusic"); if (mediaPlayer != null) { pausePosition = 0; mediaPlayer.pause(); mediaPlayer.seekTo(0); mediaPlayer.stop(); } } public int getPlayPosition() { /*返回播放进度*/ Log.d("MusicService----5----", "getPlayPosition"); if(mediaPlayer!=null) { return mediaPlayer.getCurrentPosition(); } return 0; } public void seekToPosition(int msec) { /*设置播放进度*/ Log.d("MusicService----6----", "seekToPosition"); if(mediaPlayer!=null) { if(!mediaPlayer.isPlaying()) myBinder.playMusic(); playState=false; mediaPlayer.seekTo(msec); } } public int getMediaPlayState() { /*返回播放状态*/ Log.d("MusicService----7----", "getMediaPlayState"); if(mediaPlayer!=null) { if(mediaPlayer.isPlaying()) return 1; else if(playState) return 2; else return 0; } else return 0; } public String getMusicSinger(){ Log.d("MusicService----8----", "getMusicSinger"); if(mediaPlayer!=null) return music_singer; else return ""; } public String getMusicSong() { Log.d("MusicService----9----", "getMusicSong"); if(mediaPlayer!=null) return music_song; else return ""; } public int getMusicId(){ Log.d("MusicService----10----", "getMusicId"); if(mediaPlayer!=null) return music_Id; else return -1; } public int getMusicDuration(){ Log.d("MusicService----11----", "getMusicDuration"); if(mediaPlayer!=null) return mediaPlayer.getDuration(); else return -1; } public void setPlayModule(){ /*设置播放模式*/ if(playModule) playModule=false; else playModule=true; } public boolean getPlayModule(){ return playModule; } }

MusicListActivity.java中与播放控制有关的关键代码

private void serviceConn() { serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mMyBinder = (MusicService.MyBinder) iBinder; //如果启动时正在播放 if(mMyBinder.getMediaPlayState()==1) { playIv.setImageResource(R.mipmap.icon_pause); songTv.setText(mMyBinder.getMusicSong()); singerTv.setText(mMyBinder.getMusicSinger()); currentId=mMyBinder.getMusicId(); //设置进度条大小 seekBar.setMax(mMyBinder.getMusicDuration()); Log.d("currentId", Integer.toString(currentId)); } //传递播放列表 mMyBinder.setDatas(list); //初始化进度条 seekBar.setProgress(0); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { //响应用户点击设置进度条 if(b && currentId!=-1 &¤tId!=-2) { mMyBinder.seekToPosition(seekBar.getProgress()); playIv.setImageResource(R.drawable.ripple_pause); } else if(b){ Toast.makeText(MusicListActivity.this, "请选择播放音乐", Toast.LENGTH_SHORT).show(); seekBar.setProgress(0); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { //mMyBinder.seekToPosition(seekBar.getProgress()); } }); //设置进度条控制线程 handler = new Handler(); runnable = new Runnable() { private int pre=-1, pos; @Override public void run() { pos = mMyBinder.getPlayPosition(); if(currentId!=-1 && currentId!=-2) seekBar.setProgress(pos); Log.d("RunnablePos", String.valueOf(pos)); if(pre!=pos) handler.postDelayed(runnable, 1000); else handler.postDelayed(runnable, 2000); //修复最后一首时播放图标bug pre = pos; } }; handler.post(runnable); } @Override public void onServiceDisconnected(ComponentName componentName) { } }; } private void setEventListener() { /* 设置点击事件*/ //设置单曲循环/列表循环 albumIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mMyBinder.setPlayModule(); if(mMyBinder.getPlayModule()){ Toast.makeText(MusicListActivity.this, "单曲循环", Toast.LENGTH_SHORT).show(); albumIv.setImageResource(R.mipmap.icon_song2_loop_blue); } else { Toast.makeText(MusicListActivity.this, "列表循环", Toast.LENGTH_SHORT).show(); albumIv.setImageResource(R.mipmap.icon_song2); } } }); }

MusicIntentService.java处理异步请求,点击歌曲后可使相应相应歌曲信息显示在下方播放栏中

private Intent intent; private MusicIntentService(Context context){ super(null); intent=new Intent(context ,MusicService.class); } public MusicIntentService() { super(null); } Intent getIntent(){ return intent; } @Override public void onCreate() { super.onCreate(); } static MusicIntentService get(Context context){ if(musicIntent==null){ musicIntent=new MusicIntentService(context); } return musicIntent; } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override protected void onHandleIntent(Intent intent) { if (intent != null) { intent.setAction("UI_info"); sendBroadcast(intent); } } }

MusicListActivity中对应的函数

private void setReceiver() { myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { songTv.setText(intent.getStringExtra("music_song")); singerTv.setText(intent.getStringExtra("music_singer")); currentId = intent.getIntExtra("music_id", -1); seekBar.setMax(intent.getIntExtra("music_duration", 0)); } }; IntentFilter intentFilter = new IntentFilter("UI_info"); registerReceiver(myReceiver, intentFilter); } 播放历史功能

MusicService.java中对应的更新历史记录函数

public class MyBinder extends Binder { public void updateHistory(int position){ if(position!=-1) {//歌曲非空 song= mDatas.get(position);//获取歌曲的id } if(song!=null){//歌曲非空 if(listHistory.contains(song)) { listHistory.remove(song);//存在歌曲则移除,防止重复 } } listHistory.addFirst(song);//添加元素至首部,使新点歌曲永远位于顶部 } }

MusicListActivity.java中相应点击事件,点击歌曲触发事件

adapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override //点击歌曲后即可存入播放历史 public void OnItemClick(View view, int position) { Song bean = list.get(position);//position为歌曲id,这是为了获取歌曲的位置 mMyBinder.updateHistory(position);//更新历史记录 song=bean; playMusicOnService(position); } });

MusicListActivity.java中清空历史记录的函数

public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_delete: if(positionList==1){//如果当前为历史记录歌单 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("是否清空历史记录?") .setIcon(android.R.drawable.ic_dialog_info) .setNegativeButton("取消", null); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { list.clear();//实时更新数据源 listSheet=MusicListSheet.get(getApplicationContext()); listHistory=listSheet.getSheet().get(1); listHistory.getList().clear();// adapter.notifyDataSetChanged();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 Toast.makeText(MusicListActivity.this, "清除成功", Toast.LENGTH_SHORT).show(); } }); builder.show(); adapter.notifyDataSetChanged();//更新显示 } 歌单操作功能

歌单JavaBean数据库文件Sheet.java,主要存储数据如下

public class Sheet implements Serializable { private String name;//歌单名 private List list;//歌曲列表 public String getNumString(){ if(list!=null) { return " " + list.size() + " 首歌曲"; }//显示歌曲数目 return " " + 0 + " 首歌曲"; }

歌单适配器SheetAdapter.java关键代码

protected void convert(BaseViewHolder viewHolder, Sheet item) { viewHolder.setText(R.id.name_text_view, item.getName()); viewHolder.setText(R.id.number_text_view,item.getNumString()); }

MusicListSheet.java对歌单进行初始化

private MusicListSheet(Context context){ sheet=new ArrayList(); Sheet listAllMusic=new Sheet("全部音乐");//默认歌单 listAllMusic.setList(MusicUtils.getMusicData(context)); Sheet listHistory=new Sheet("播放历史",1);//默认歌单 //Sheet listRecommendation=new Sheet("推荐歌单",2); sheet.add(0,listAllMusic); sheet.add(1,listHistory); // sheet.add(2,listRecommendation); }

歌单对应布局文件item_sheet.xml,效果如下 在这里插入图片描述 MainActivity.java中相应点击事件代码 点击歌单跳转事件

public void onItemClick(BaseQuickAdapter adapter, View view, int position) { Intent intent = new Intent(MainActivity.this, MusicListActivity.class); //点击跳转至歌单 intent.putExtra("CLICK_POSITION",position);//点击的歌单位置,相应跳转 startActivity(intent); }

新建歌单事件 MusicListActivity.java相应点击函数

public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_add) {//nameNewList 弹窗输入 final EditText inputServer = new EditText(this); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("输入歌单名称") .setView(inputServer) .setNegativeButton("取消", null); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String nameNewList = inputServer.getText().toString(); listSheet.add(new Sheet(nameNewList)); //实时更新数据源 setSheet.clear(); setSheet.addAll(listSheet.getSheet()); //先清空歌单,再加入新歌单列表,实时更新列表 sheetAdapter.notifyDataSetChanged(); } }); builder.show(); sheetAdapter.notifyDataSetChanged(); return true; } return super.onOptionsItemSelected(item); }

MusicListActivity.java中相应点击事件代码 删除歌单事件

public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_delete: if(positionList!=0&&positionList!=1) {//非默认歌单时才可删除 //历史歌单点击按钮对应为清空播放历史,全部音乐歌单对应按钮则提示不可删除 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("是否删除此列表?") .setIcon(android.R.drawable.ic_dialog_info) .setNegativeButton("取消", null); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //setSheet.clear(); //setSheet.addAll(listSheet.getSheet()); // sheetAdapter.notifyDataSetChanged(); listSheet.getSheet().remove(positionList);//移除歌单 setSheet.clear();//清空列表 setSheet.addAll(listSheet.getSheet()); sheetAdapter.notifyDataSetChanged();//添加更新后列表,更新数据 Toast.makeText(MusicListActivity.this, "删除成功", Toast.LENGTH_SHORT).show(); finish(); sheetAdapter.notifyDataSetChanged(); } }); builder.show(); adapter.notifyDataSetChanged(); }else if(positionList==0){//positionList==1时再上面 Toast.makeText(this, "此列表不可删除", Toast.LENGTH_SHORT).show(); } }

添加歌曲事件 点击要添加的歌曲 MusicListActivity.java对应点击事件函数:

addImageView.setOnClickListener(new View.OnClickListener() { @Override//点击进入添加歌曲界面 public void onClick(View view) { Intent addIntent = new Intent(MusicListActivity.this, SheetAdd.class); startActivityForResult(addIntent,0); } });

在这里插入图片描述

SheetAdd.java对应关键代码,点击要加入的歌单

public void onItemClick(BaseQuickAdapter adapter, View view, int position) { Intent intent=new Intent(); intent.putExtra("ADD_LIST",position); setResult(1, intent); finish(); }

删除歌曲事件 MusicListActivity.java对应点击事件函数,点击修改按钮进入修改界面

public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: if(positionList!=0&&positionList!=1) {//默认列表不可修改 Intent intentDrag = new Intent(MusicListActivity.this, ItemDragActivity.class); intentDrag.putExtra("POSITION",positionList);//传入歌单位置 startActivity(intentDrag); }else{//默认列表不可修改 Toast.makeText(this, "此列表不可修改", Toast.LENGTH_SHORT).show(); } adapter.notifyDataSetChanged(); return true; default: return super.onOptionsItemSelected(item); } }

ItemDragActivity.java对应函数,通过滑动歌曲进行删除

OnItemDragListener onItemDragListener = new OnItemDragListener() { @Override public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){ list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} @Override public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} @Override public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} }; OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() { @Override public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} @Override public void clearView(RecyclerView.ViewHolder viewHolder, int pos) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} @Override public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} @Override public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) { list.clear();//实时更新数据源 list.addAll(sheet.getList());//实时更新数据源 adapter.notifyDataSetChanged();} };

相应适配器代码

protected void convert(BaseViewHolder holder, Song item) { if(item!=null) { holder.setText(R.id.music_num, item.getId()); holder.setText(R.id.music_song, item.getSong()); holder.setText(R.id.music_singer, item.getSinger()); holder.setText(R.id.music_album, item.getAlbum()); SimpleDateFormat sdf = new SimpleDateFormat("mm:ss"); String time = sdf.format(new Date(item.getDuration())); holder.setText(R.id.music_duration, time); } // (String)item.getDuration() } 搜索功能

搜索功能分为两部分,在歌单页面则搜索相应歌单,在歌曲页面则搜索相应歌曲 两个判定函数,中文歌曲可直接进行字符匹配,英文歌曲一般每个单词首字母大写 所以判定条件为,无论大小写输入,都可以按 每个单词首字母大写,其余小写搜索

public String capitalize(String string) {//搜索 首字母大写 String finalstr=""; String[] a= string.split(" "); for(int i=0;i//搜索 和上面反过来 String finalstr=""; String[] a= string.split(" "); for(int i=0;i //设置SearchView默认是否自动缩小为图标 musicSearch.setIconifiedByDefault(true); musicSearch.setFocusable(false); //设置搜索框监听器 musicSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { //点击搜索按钮时激发 return false; } @Override public boolean onQueryTextChange(String s) { //输入时激发 if(TextUtils.isEmpty(s)){ //没有过滤条件内容 list.clear(); list.addAll(sheet.getList()); adapter.notifyDataSetChanged(); } else { //根据输入内容对RecycleView搜索 list.clear(); for (Song bean:sheet.getList()){ if(bean.getSong().contains( capitalize(s))|bean.getSong().contains( capitalize2(s))|bean.getSong().contains(s.toLowerCase()) | bean.getSong().contains(s.toUpperCase()) |bean.getSong().contains(s)) { list.add(bean); } } adapter.notifyDataSetChanged(); } return true; } }); }

MainActivity.java搜索歌单:

private void setSearchList() { //设置SearchView默认是否自动缩小为图标 musicSearch.setIconifiedByDefault(true); musicSearch.setFocusable(false); //设置搜索框监听器 musicSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String s) { //点击搜索按钮时激发 return false; } @Override public boolean onQueryTextChange(String s) { //输入时激发 if(TextUtils.isEmpty(s)){ //没有过滤条件内容 setSheet.clear(); setSheet.addAll(listSheet.getSheet()); sheetAdapter.notifyDataSetChanged(); } else { //根据输入内容对RecycleView搜索 setSheet.clear(); for (Sheet bean: listSheet.getSheet()){ if(bean.getName().contains( capitalize(s))|bean.getName().contains( capitalize2(s))|bean.getName().contains(s.toLowerCase()) | bean.getName().contains(s.toUpperCase()) |bean.getName().contains(s) ) { setSheet.add(bean); } } sheetAdapter.notifyDataSetChanged(); } return true; } }); } private void setEventListener() { //点击弹出侧边栏 menuIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawerLayout.openDrawer(GravityCompat.START); } }); } //点击相应侧边栏页面 private void setDrawer() { navigationView.setItemIconTintList(null); navigationView.getChildAt(0).setVerticalScrollBarEnabled(false); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { switch (menuItem.getItemId()){ case R.id.item_0: Log.d("ItemSelectedListener", "item0"); //fragmentManager.popBackStackImmediate(null, 1); transaction = fragmentManager.beginTransaction(); transaction.remove(fragment_about).commit(); transaction = fragmentManager.beginTransaction(); transaction.remove(fragment_introduction).commit(); transaction = fragmentManager.beginTransaction(); transaction.remove(fragment_message).commit(); // Toast.makeText(MainActivity.this, "!!!!", Toast.LENGTH_SHORT).show(); break; case R.id.item_2: //弹出功能介绍 transaction = fragmentManager.beginTransaction(); transaction.replace(R.id.fragment, fragment_introduction).commit(); Log.d("ItemSelectedListener", "item2"); // Toast.makeText(MainActivity.this, "2", Toast.LENGTH_SHORT).show(); break; case R.id.item_3: //退出 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("确定要退出吗?") .setIcon(android.R.drawable.ic_dialog_info) .setNegativeButton("取消", null); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "退出成功", Toast.LENGTH_SHORT).show(); finish(); sheetAdapter.notifyDataSetChanged(); } }); builder.show(); break; } sheetAdapter.notifyDataSetChanged(); drawerLayout.closeDrawer(GravityCompat.START); transaction.addToBackStack(null); return true; } }); //设置滑动主activity跟随 drawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() { @Override public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { //获取高度宽度 DisplayMetrics metrics = getResources().getDisplayMetrics(); Display display = MainActivity.this.getWindowManager().getDefaultDisplay(); display.getMetrics(metrics); //设置activity高度,注意要加上状态栏高度 RelativeLayout relativeLayout = findViewById(R.id.main_activity); relativeLayout.layout(drawerView.getRight(), Notification_height, drawerView.getRight()+metrics.widthPixels, metrics.heightPixels); } @Override public void onDrawerOpened(@NonNull View drawerView) { } @Override public void onDrawerClosed(@NonNull View drawerView) { } @Override public void onDrawerStateChanged(int newState) { } }); } 精化设计

SplashActivity,动态获取权限

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); // setContentView(R.layout.activity_splash); initView(); final RxPermissions rxPermissions = new RxPermissions(this); rxPermissions .request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.INTERNET, Manifest.permission.ACCESS_NETWORK_STATE) .subscribe(granded -> { if (granded) { //获取权限后 new Handler().postDelayed(new Runnable() { public void run() { Intent intent = new Intent(SplashActivity.this, MainActivity.class); //第二个参数即为执行完跳转后的Activity startActivity(intent); SplashActivity.this.finish(); //关闭splashActivity,将其回收,否则按返回键会返回此界面 } }, SPLASH_DISPLAY_LENGHT); Log.d("rxRermision", "get"); } else { Toast.makeText(this, "未获取到存储权限", Toast.LENGTH_LONG).show(); Log.d("rxRermision", "denied"); } });

设置启动时动画,初始化控件,关键代码:

private void initView() { //加载视频资源控件 videoview = (CustomVideoView) findViewById(R.id.videoview); //设置播放加载路径 //videoview.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.video)); videoview.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.splash)); //播放 videoview.start(); //循环播放 videoview.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { videoview.start(); } });} 侧边栏功能

包含3个侧边栏activity,分别为Frag_introduction.java, Frag_message.java, Frag_quit.java 分别为介绍,返回首页,退出功能 MainActivity.java中的监听事件关键代码:

界面展示

主界面 在这里插入图片描述 在这里插入图片描述

启动加载页面 在这里插入图片描述 询问授权 在这里插入图片描述 主页面(歌单页面) 在这里插入图片描述 添加歌单 在这里插入图片描述

搜索功能演示: 在这里插入图片描述 在这里插入图片描述 歌单页面(以全部音乐为例) 在这里插入图片描述 侧边栏界面 在这里插入图片描述

参考资料

https://www.bilibili.com/video/BV1oJ41197fi?from=search&seid=570955563504969972

https://blog.csdn.net/dl10210950/article/details/52248893

项目链接

链接:https://github.com/FallingForYouForever/MusicPlayer.git



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有