功能简介
- 读取模拟器中音乐文件;
- 列表展示,获取歌曲详细信息:歌名、歌手名、专辑名、专辑封面、播放时间等;
- 基本功能:上下切歌,播放暂停、进度条显示与点击跳转。
- 成品效果图:
Mediaplayer基本状态
Mediaplayer播放器主要涉及以下状态,通过调用图中函数进行状态跳转。
- Idle //mPlayer刚被创建或者重置之后还未被初始化时的状态;
- Initialized //setDataSource()加载资源后进入初始化状态;
- Preparing和Prepared //Preparing是准备中状态, Prepared是就绪状态,可进行播放属性的设置。
- Started和Paused //播放和暂停状态,调用start()和pause()进行跳转
- Stop //停止状态,当在某个时刻调用了stop()之后,就需要再次调用prepare()使mPlayer转到就绪状态。
- PlaybackCompleted //播放完毕状态,如果设置了循环播放模式,当播放完毕的时候,mPlayer会重新进入到Started状态
- End //End是结束状态,当调用release()时,会释放播放引擎中与mPlayer相关的资源,这时就无法再转换到其他状态了。
- Error //当mPlayer出现一些错误(例如,格式错误),就会调用OnErrorListener.OnError()方法进入到Error状态。
项目难点详解
添加资源文件
- 工程项目添加
项目res资源文件夹 -> 新建raw资源文件夹 -> 添加资源
- 模拟器添加音乐
1.打开模拟器存储目录,运行模拟器 -> View -> Tools Windows -> Device File Explorer;
2.存储音乐至sdcard/Music/ 或storage/emulated/0/Music/;
3.右键点击Upload,选择音乐资源加载。
权限
- 静态权限
读权限&写权限,直接声明使用
[AndroidManifest.xml]
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- 动态权限
因为涉及SD卡读取,需要使用动态权限,Android6.0后权限分为静态权限与动态权限,需要分开定义。如果读取工程项目中指定资源资源文件,使用静态权限即可。
[MainActivity.java] 中声明使用,分为权限获取函数及其回调函数
//动态权限申请函数if (ContextCompat.checkSelfPermission( MainActivity.this,Manifest.permission.WRITE_APN_SETTINGS ) != PackageManager.PERMISSION_GRANTED) //判断是否已经授权{//申请权限 三个参数:1.Activity实例;2.String数组,存放权限;3.唯一请求码ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1 );}else{//填写功能函数loadLocalMusicData(); //权限请求失败,则加载本地数据源,请求成功则调用回调函数中的加载,不管成功与否都会调用}//动态权限获取函数的回调函数@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult( requestCode, permissions, grantResults );switch (requestCode) {case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//填写功能函数loadLocalMusicData(); //申请权限成功,扫描模拟器存储,加载资源} else {finish();Toast.makeText( this, "denied!", Toast.LENGTH_SHORT ).show();}}}
媒体库资源更新
在模拟器中添加资源,并通过动态权限进行读取的过程中,Android系统并不会时时全局扫描资源,通常开关机模拟器时才扫描,所以需要进行媒体库的主动扫描资源。
private void loadLocalMusicData() {/* 更新媒体库mp3文件*/String file_path = "storage/emulated/0/Music";MediaScannerConnection.scanFile( this,new String[]{file_path.toString()},
// null,new String[]{"mp3"}, //指定扫描mp3文件,缩短时间new MediaScannerConnection.OnScanCompletedListener() {@Overridepublic void onScanCompleted(String path, Uri uri) {Log.i( "ExternalStorage", "Scanned" + path + ":" );Log.i( "ExternalStorage", "->" + uri);}} );
读取Android多媒体资源文件
这里使用MediaStore库,其是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。
- MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息
- MediaStore.Audio: 存放音频信息
- MediaStore.Image: 存放图片信息
- MediaStore.Vedio: 存放视频信息
模块化读取资源信息,如mp3文件中的歌曲名、歌手名、专辑名、时长、存放路径等信息。
- MediaStore.Audio.Media.TITLE //歌曲标题
- MediaStore.Audio.Media.ARTIST //歌手名
- MediaStore.Audio.Media.ALBUM //专辑名
- MediaStore.Audio.Media.DATA //路径
- MediaStore.Audio.Media.DURATION //视频时长
- MediaStore.Audio.Media.ALBUM_ID //相册名
[MainActivity.java]
/* 加载本地存储当中的音乐mp3文件到集合当中*/
// 1.获取ContentResolver对象ContentResolver resolver = getContentResolver();
// 2.获取本地音乐存储的Uri地址Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// 3 开始查询地址 查询接口Cursor cursor = resolver.query(uri, null, null, null, null);
// 4.遍历Cursorint id = 0;while (cursor.moveToNext()) {String song = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); //歌曲标题String singer = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); //歌手名String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //专辑名id++;String sid = String.valueOf(id); //序列号String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //路径long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); //视频时长SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");String time = sdf.format(new Date(duration));
// 获取专辑图片主要是通过album_id进行查询String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//相册名String albumArt = getAlbumArt(album_id);
// 将一行当中的数据封装到对象当中LocalMusicBean bean = new LocalMusicBean(sid, song, singer, album, time, path, albumArt); //每一首歌的信息封装mDatas.add(bean);}
// 数据源变化,提示适配器更新adapter.notifyDataSetChanged();
获取歌曲封面
//获取歌曲的封面private void loadCover(String path){MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();mediaMetadataRetriever.setDataSource( path );byte[] cover = mediaMetadataRetriever.getEmbeddedPicture();Bitmap bitmap = BitmapFactory.decodeByteArray( cover, 0, cover.length );albumIv.setImageBitmap( bitmap );}
获取歌曲的时间以及进度条跳转
- 两个TextView:tv_star, tv_end分别时时显示当前时间,时间总长;
- 一个SeekBar实现进度动态显示与跳转;
- 延时50ms更新时间进度条;
- SeekBar回调函数,点击时、移动时、确定时。
private void SeekBarSet(){/*新增seekbar进度条*/int duration = mediaPlayer.getDuration(); //获取视频总时间seekBar.setMax( duration ); //将音乐总时间设置为Seekbar的最大值Timer timer = new Timer( );timer.schedule( new TimerTask() {@Overridepublic void run() {
// if (!currentPausePositionInSong){seekBar.setProgress( mediaPlayer.getCurrentPosition() );
// }}},0,50);seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {int time_end = mediaPlayer.getDuration() / 1000 ; //获取视频时长tv_end.setText(calaculateTime( time_end ));int time_now = mediaPlayer.getCurrentPosition() / 1000;tv_star.setText(calaculateTime( time_now ) );}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {mediaPlayer.seekTo( seekBar.getProgress() );
// tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));}} );
}
项目部分代码
使用控件列表
控件类型 | 功能 | 详细控件 |
---|---|---|
ImageView | 图形按键 | 上一首、下一首、播放、暂停 |
TextView | 文本栏 | 歌曲名、歌手名、专辑名、单前播放时间、总时长 |
RecyclerView | 滑动列表 | 加载各歌曲信息的列表 |
LocalMusicAdapter | 横条信息展示栏 | 加载每一首歌曲信息的基本信息 |
SeekBar | 进度条 | 显示当前歌曲进度信息 |
基本控件为以上所述,前端代码就不贴了
项目详细代码
[MainActivity.java] 主类,包含各控件定义与各监听器定义及功能
package com.example.musicplayer_2;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private MediaPlayer mediaPlayer;private ImageView nextIv,playIv,lastIv,albumIv; //图像控件:private TextView singerTv,songTv; //文本信息:歌手名、歌名private RecyclerView musicRv; //类似ListView 可横向滚动private SeekBar seekBar;private TextView tv_star, tv_end;private List<LocalMusicBean> mDatas; //数据源 自定义类数组 存放各歌曲信息private LocalMusicAdapter adapter; //歌曲横条信息控件设置private int currnetPlayPosition = -1; //记录当前正在播放的音乐的位置private int currentPausePositionInSong = 0; //记录暂停音乐时进度条的位置@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );setContentView( R.layout.activity_main );initView(); //控件定义与绑定 减少代码量mediaPlayer = new MediaPlayer();mDatas = new ArrayList<>(); //任意类型数组//创建适配器对象adapter = new LocalMusicAdapter(this, mDatas); //传参context,mDatasmusicRv.setAdapter(adapter);//设置布局管理器LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);musicRv.setLayoutManager(layoutManager);//动态权限申请if (ContextCompat.checkSelfPermission( MainActivity.this,Manifest.permission.WRITE_APN_SETTINGS ) != PackageManager.PERMISSION_GRANTED) //判断是否已经授权{//申请权限 三个参数:1.Activity实例;2.String数组,存放权限;3.唯一请求码ActivityCompat.requestPermissions( MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1 );}else{loadLocalMusicData(); //权限请求失败,则加载本地数据源,请求成功则调用回调函数中的加载,不管成功与否都会调用}// loadLocalMusicData(); //加载本地数据源setEventListener(); //设置每一项的点击事件}//动态权限获取函数的回调函数@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult( requestCode, permissions, grantResults );switch (requestCode) {case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {loadLocalMusicData(); //申请权限成功,扫描模拟器存储,加载资源} else {finish();Toast.makeText( this, "denied!", Toast.LENGTH_SHORT ).show();}}}private void loadLocalMusicData() {/* 更新媒体库mp3文件*/String file_path = "storage/emulated/0/Music";MediaScannerConnection.scanFile( this,new String[]{file_path.toString()},
// null,new String[]{"mp3"},new MediaScannerConnection.OnScanCompletedListener() {@Overridepublic void onScanCompleted(String path, Uri uri) {Log.i( "ExternalStorage", "Scanned" + path + ":" );Log.i( "ExternalStorage", "->" + uri);}} );/* 加载本地存储当中的音乐mp3文件到集合当中*/
// 1.获取ContentResolver对象ContentResolver resolver = getContentResolver();
// 2.获取本地音乐存储的Uri地址Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// 3 开始查询地址 查询接口Cursor cursor = resolver.query(uri, null, null, null, null);
// 4.遍历Cursorint id = 0;while (cursor.moveToNext()) {String song = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); //歌曲标题String singer = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); //歌手名String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)); //专辑名id++;String sid = String.valueOf(id); //序列号String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //路径long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); //视频时长SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");String time = sdf.format(new Date(duration));
// 获取专辑图片主要是通过album_id进行查询String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//相册名String albumArt = getAlbumArt(album_id);
// 将一行当中的数据封装到对象当中LocalMusicBean bean = new LocalMusicBean(sid, song, singer, album, time, path, albumArt); //每一首歌的信息封装mDatas.add(bean);}
// 数据源变化,提示适配器更新adapter.notifyDataSetChanged();}private void initView() {/* 初始化控件的函数*/nextIv = findViewById(R.id.local_music_bottom_iv_next);playIv = findViewById(R.id.local_music_bottom_iv_play);lastIv = findViewById(R.id.local_music_bottom_iv_last);albumIv = findViewById(R.id.local_music_bottom_iv_icon);singerTv = findViewById(R.id.local_music_bottom_tv_singer);songTv = findViewById(R.id.local_music_bottom_tv_song);musicRv = findViewById(R.id.local_music_rv);nextIv.setOnClickListener(this);lastIv.setOnClickListener(this);playIv.setOnClickListener(this);seekBar = findViewById( R.id.local_music_bottom_tv_time ); //进度条定义tv_star = findViewById( R.id.local_music_bottom_tv_time_star );tv_end = findViewById( R.id.local_music_bottom_tv_time_end );}private void setEventListener() {/* 设置每一项的点击事件*/adapter.setOnItemClickListener(new LocalMusicAdapter.OnItemClickListener() {@Overridepublic void OnItemClick(View view, int position) {currnetPlayPosition = position;LocalMusicBean musicBean = mDatas.get(position);playMusicInMusicBean(musicBean);}});}public void playMusicInMusicBean(LocalMusicBean musicBean) { //传入一首歌 信息/*根据传入对象播放音乐*///设置底部显示的歌手名称和歌曲名singerTv.setText(musicBean.getSinger()); //获取当前信息并设置songTv.setText(musicBean.getSong());stopMusic();
// 重置多媒体播放器mediaPlayer.reset();
// 设置新的播放路径try {mediaPlayer.setDataSource(musicBean.getPath());String albumArt = musicBean.getAlbumArt();Log.i("lsh123", "playMusicInMusicBean: albumpath=="+albumArt);Bitmap bm = BitmapFactory.decodeFile(albumArt);Log.i("lsh123", "playMusicInMusicBean: bm=="+bm);albumIv.setImageBitmap(bm);playMusic();SeekBarSet(); //设置进度条及其时间显示loadCover(musicBean.getPath());} catch (Exception e) {e.printStackTrace();}}private void SeekBarSet(){/*新增seekbar进度条*/int duration = mediaPlayer.getDuration(); //获取视频总时间seekBar.setMax( duration ); //将音乐总时间设置为Seekbar的最大值Timer timer = new Timer( );timer.schedule( new TimerTask() {@Overridepublic void run() {
// if (!currentPausePositionInSong){seekBar.setProgress( mediaPlayer.getCurrentPosition() );
// }}},0,50);seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int i, boolean b) {int time_end = mediaPlayer.getDuration() / 1000 ; //获取视频时长tv_end.setText(calaculateTime( time_end ));int time_now = mediaPlayer.getCurrentPosition() / 1000;tv_star.setText(calaculateTime( time_now ) );}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {mediaPlayer.seekTo( seekBar.getProgress() );
// tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));}} );}/** 点击播放按钮播放音乐,或者暂停从新播放* 播放音乐有两种情况:* 1.从暂停到播放* 2.从停止到播放* */private void playMusic() {/* 播放音乐的函数*/if (mediaPlayer!=null&&!mediaPlayer.isPlaying()) {if (currentPausePositionInSong == 0) { //如果已经停止播放try {mediaPlayer.prepare(); //重新准备播放mediaPlayer.start();} catch (Exception e) {e.printStackTrace();}}else{
// 从暂停到播放mediaPlayer.seekTo(currentPausePositionInSong);mediaPlayer.start();}
// playIv.setImageResource(R.mipmap.icon_pause);}}private void pauseMusic() {/* 暂停音乐的函数*/if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {currentPausePositionInSong = mediaPlayer.getCurrentPosition(); //获取进度条mediaPlayer.pause();playIv.setImageResource(R.mipmap.icon_play);}}private void stopMusic() {/* 停止音乐的函数*/if (mediaPlayer!=null) {currentPausePositionInSong = 0;mediaPlayer.pause(); //播放器暂停mediaPlayer.seekTo(0); //调至0mediaPlayer.stop(); //停止playIv.setImageResource(R.mipmap.icon_play); //显示图标}}@Overrideprotected void onDestroy() {super.onDestroy();stopMusic();}/*进度条时间换算与格式转变*///时间格式换算1public String formattime(long time){String min= (time/(1000*60))+"";String second= (time%(1000*60)/1000)+"";if(min.length()<2){min = 0 + min;}if(second.length()<2){second = 0 + second;}return min +":"+ second;}//时间格式换算2public String calaculateTime(int time){int minute, second;if(time > 60){minute = time / 60; //分钟取整second = time % 60; //秒钟取余//分钟再0~9if(minute >= 0 && minute < 10){ //0x:0x//判断秒if(second >= 0 && second < 10){return "0"+minute+":"+"0"+second;}else {return "0"+minute+":"+second;}}else {//分钟大于10再判断秒if(second >= 0 && second < 10){return minute+":"+"0"+second;}else {return minute+":"+second;}}}else if(time < 60){second = time;if(second >= 0 && second < 10){return "00:"+"0"+second;}else {return "00:"+ second;}}return null;}private String getAlbumArt(String album_id) {String mUriAlbums = "content://media/external/audio/albums";String[] projection = new String[]{"album_art"};Cursor cur = this.getContentResolver().query(Uri.parse(mUriAlbums + "/" + album_id),projection, null, null, null);String album_art = null;if (cur.getCount() > 0 && cur.getColumnCount() > 0) {cur.moveToNext();album_art = cur.getString(0);}cur.close();cur = null;return album_art;}private void loadCover(String path){MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();mediaMetadataRetriever.setDataSource( path );byte[] cover = mediaMetadataRetriever.getEmbeddedPicture();Bitmap bitmap = BitmapFactory.decodeByteArray( cover, 0, cover.length );albumIv.setImageBitmap( bitmap );}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.local_music_bottom_iv_last: //上一首if (currnetPlayPosition ==0) {Toast.makeText(this,"已经是第一首了,没有上一曲!",Toast.LENGTH_SHORT).show();return;}currnetPlayPosition = currnetPlayPosition-1; //序号索引-1LocalMusicBean lastBean = mDatas.get(currnetPlayPosition); //从数组中获取上一首信息playMusicInMusicBean(lastBean);break;case R.id.local_music_bottom_iv_next: //下一首if (currnetPlayPosition ==mDatas.size()-1) {Toast.makeText(this,"已经是最后一首了,没有下一曲!",Toast.LENGTH_SHORT).show();return;}currnetPlayPosition = currnetPlayPosition+1;LocalMusicBean nextBean = mDatas.get(currnetPlayPosition);playMusicInMusicBean(nextBean);break;case R.id.local_music_bottom_iv_play:if (currnetPlayPosition == -1) {
// 并没有选中要播放的音乐Toast.makeText(this,"请选择想要播放的音乐",Toast.LENGTH_SHORT).show();return;}if (mediaPlayer.isPlaying()) {
// 此时处于播放状态,需要暂停音乐pauseMusic();}else {
// 此时没有播放音乐,点击开始播放音乐playMusic();}break;}}
}
[LocalMusicBean.java] 歌曲信息封装类,包含歌曲各信息
package com.example.musicplayer_2;/*** author : harrison* e-mail : harrison.zfx@gmail.com* data : zfx上午10:29* version: 1.0*/
public class LocalMusicBean {private String id; //歌曲idprivate String song; //歌曲名称private String singer; //歌手名称private String album; //专辑名称private String duration; //歌曲时长private String path; //歌曲路径private String albumArt; //专辑地址public LocalMusicBean() {}public LocalMusicBean(String id, String song, String singer, String album, String duration, String path, String albumArt) {this.id = id;this.song = song;this.singer = singer;this.album = album;this.duration = duration;this.path = path;this.albumArt = albumArt;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getSong() {return song;}public void setSong(String song) {this.song = song;}public String getSinger() {return singer;}public void setSinger(String singer) {this.singer = singer;}public String getAlbum() {return album;}public void setAlbum(String album) {this.album = album;}public String getDuration() {return duration;}public void setDuration(String duration) {this.duration = duration;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getAlbumArt() {return albumArt;}public void setAlbumArt(String albumArt) {this.albumArt = albumArt;}
}
[LocalMusicAdapter.java] 歌曲横向展示类
package com.example.musicplayer_2;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import java.util.List;/*** author : harrison* e-mail : harrison.zfx@gmail.com* data : zfx上午10:49* version: 1.0*/
public class LocalMusicAdapter extends RecyclerView.Adapter<LocalMusicAdapter.LocalMusicViewHolder>{private Context context;private List<LocalMusicBean>mDatas;private OnItemClickListener onItemClickListener;public void setOnItemClickListener(OnItemClickListener onItemClickListener) { //监听器参数传入this.onItemClickListener = onItemClickListener;}public interface OnItemClickListener{public void OnItemClick(View view,int position);}public LocalMusicAdapter(Context context, List<LocalMusicBean> mDatas) { //构造函数传入参数 context上下文,数据集this.context = context;this.mDatas = mDatas;}@NonNull@Overridepublic LocalMusicViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(context).inflate(R.layout.item_local_music,parent,false);LocalMusicViewHolder holder = new LocalMusicViewHolder(view);return holder;}@Overridepublic void onBindViewHolder(@NonNull LocalMusicViewHolder holder, final int position) {LocalMusicBean musicBean = mDatas.get(position);holder.idTv.setText(musicBean.getId());holder.songTv.setText(musicBean.getSong());holder.singerTv.setText(musicBean.getSinger());holder.albumTv.setText(musicBean.getAlbum());holder.timeTv.setText(musicBean.getDuration());holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onItemClickListener.OnItemClick(v,position);}});}@Overridepublic int getItemCount() {return mDatas.size();}class LocalMusicViewHolder extends RecyclerView.ViewHolder{TextView idTv,songTv,singerTv,albumTv,timeTv;public LocalMusicViewHolder(View itemView) {super(itemView);idTv = itemView.findViewById(R.id.item_local_music_num); //序号songTv = itemView.findViewById(R.id.item_local_music_song); //歌名singerTv = itemView.findViewById(R.id.item_local_music_singer); //歌手名albumTv = itemView.findViewById(R.id.item_local_music_album); //专辑名timeTv = itemView.findViewById(R.id.item_local_music_durtion); //时间}}
}
前端页面代码较长就不贴了,上表中已列清基本控件使用。
挣点积分,后续会上传GitHub,完整工程地址:https://download.csdn.net/download/Harrison509/12894922