业务流程分析说明
1. 首先,在 onCreate() 方法中,我们设置了布局文件和获取了各个视图组件
的引用。还创建了一个 MediaPlayer 对象,并初始化了歌曲列表和当前歌曲索引。
2. 通 过 MediaPlayer.create() 方 法 , 根 据 当 前 歌 曲 索 引 创 建 了 一 个
MediaPlayer 对象,并设置了当前歌曲的标题和专辑封面。
3. 设置了播放按钮、上一曲按钮和下一曲按钮的点击事件监听器。
4.创建了一个定时任务 updateSeekBar(),使用 Handler 定时更新 SeekBar
的进度。
5. 在播放/暂停按钮的点击事件监听器中,通过判断 MediaPlayer 是否正在播
放来进行播放和暂停的切换,并相应地更新按钮的图标。
6. 在上一曲和下一曲按钮的点击事件监听器中,通过调用 playPreviousSong()
和 playNextSong() 方法切换到上一首和下一首歌曲,并更新歌曲标题和专辑封面。
7. 在 SeekBar 的进度变化监听器中,当用户拖动进度条时,通过调用
mediaPlayer.seekTo() 方法来改变歌曲的播放位置。
8. 在 updateSeekBar() 方法中,通过定时任务和 Handler 来更新 SeekBar 的
进度。
功能核心技术
1. 使用 MediaPlayer 类进行音乐播放,调用 MediaPlayer 的方法,可以实现音
乐的播放、暂停、停止、切换等功能。
2. 使用 SeekBar 控件实现进度条,通过设置 SeekBar 的最大值和进度,以及监
听进度变化事件,可以实现音乐播放进度的显示和拖动控制。
3. 使用 ImageButton 控件实现按钮功能,通过设置不同的图标资源来实现不同
的按钮功能,如播放、暂停、上一曲、下一曲等。
4. 使用 Handler 和定时任务实现进度更新,通过创建一个 Handler 对象,并使
用 postDelayed() 方法和 Runnable 接口,实现定时任务,用于更新进度条的显示。
5. 使用集合存储歌曲列表,使用了 List<Song> 来存储歌曲列表。通过创建自定
义的 Song 类,可以存储每首歌曲的相关信息,如歌曲标题、音频资源 ID 和封面资
源 ID。
功能模块说明与核心代码
1. 使用 MediaPlayer 类进行音乐播放,调用 MediaPlayer 的方法,可以实现音
乐的播放、暂停、停止、切换等功能。
// 初始化 MediaPlayer
mediaPlayer = MediaPlayer.create(this,
songList.get(currentSongIndex).getAudioResourceId());
2. 使用 SeekBar 控件实现进度条,通过设置 SeekBar 的最大值和进度,以及监
听进度变化事件,可以实现音乐播放进度的显示和拖动控制。
// 设置 SeekBar 的最大值
seekBar.setMax(mediaPlayer.getDuration());
// 设置 SeekBar 的进度变化监听器
seekBar.setOnSeekBarChangeListener(new
SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean
fromUser) {
if (fromUser) {
mediaPlayer.seekTo(progress);
}
}
3. 使用 ImageButton 控件实现按钮功能,通过设置不同的图标资源来实现不
同的按钮功能,如播放、暂停、上一曲、下一曲等。
// 设置按钮点击事件监听器
btnPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 实现上一曲功能
playPreviousSong();
}
});
btnPlayPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 实现播放/暂停功能
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
btnPlayPause.setImageResource(R.drawable.ic_play);
} else {
mediaPlayer.start();
btnPlayPause.setImageResource(R.drawable.ic_pause);
}
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 实现下一曲功能
playNextSong();
}
});
4. 使用 Handler 和定时任务实现进度更新,通过创建一个 Handler 对象,并
使用 postDelayed() 方法和 Runnable 接口,实现定时任务,用于更新进度条的显
示。
private void updateSeekBar() {
// 使用 Handler 定时更新 SeekBar 的进度
final android.os.Handler handler = new android.os.Handler();
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (mediaPlayer != null) {
int currentPosition = mediaPlayer.getCurrentPosition();
seekBar.setProgress(currentPosition);
}
handler.postDelayed(this, 1000); // 1000 毫秒即 1 秒更新一次
}
});
}
5. 使用集合存储歌曲列表,使用了 List<Song> 来存储歌曲列表。通过创建自
定义的 Song 类,可以存储每首歌曲的相关信息,如歌曲标题、音频资源 ID 和封面
资源 ID。
private static class Song {
private String songTitle;
private int audioResourceId;
private int coverResourceId;
public Song(String songTitle, int audioResourceId, int
coverResourceId) {
this.songTitle = songTitle;
this.audioResourceId = audioResourceId;
this.coverResourceId = coverResourceId;
}
public int getAudioResourceId() {
return audioResourceId;
}
public String getSongTitle() {
return songTitle;
}
public int getCoverResourceId() {
return coverResourceId;
}
}
// 添加歌曲...
songList = new ArrayList<>();
songList.add(new Song("裹着心的光-林俊杰", R.raw.ljj, R.drawable.ljj));
songList.add(new Song("忘了没有-王靖雯", R.raw.wjw, R.drawable.wjw));
songList.add(new Song("知足-五月天", R.raw.wyt, R.drawable.wyt));
songList.add(new Song("光年之外-邓紫棋", R.raw.dzq, R.drawable.dzq));
6.在 res/drawable 下放置图片资源
6.activity_main.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:padding="16dp"
>
<!-- 歌曲标题 -->
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/ivAlbumCover"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="161dp"
android:contentDescription="封面"
android:onClick="onImageViewClick"
android:scaleType="centerCrop"
android:src="@drawable/ljj"
android:visibility="visible" />
<TextView
android:id="@+id/tvSongTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="53dp"
android:text="歌曲标题"
android:textColor="@android:color/black"
android:textSize="20sp" />
<LinearLayout
android:layout_width="395dp"
android:layout_height="168dp"
android:layout_below="@id/tvSongTitle"
android:layout_alignParentEnd="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="21dp"
android:layout_marginEnd="22dp"
android:orientation="vertical">
<!-- 歌曲进度条 -->
<!-- 控制按钮区域 -->
<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center">
<!-- 上一曲按钮 -->
<ImageButton
android:id="@+id/btnPrevious"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="上一曲"
android:src="@drawable/ic_previous" />
<!-- 播放/暂停按钮 -->
<ImageButton
android:id="@+id/btnPlayPause"
android:layout_width="72dp"
android:layout_height="72dp"
android:background="?android:selectableItemBackgroundBorderless"
android:contentDescription="开始暂停"
android:src="@drawable/ic_play" />
<!-- 下一曲按钮 -->
<ImageButton
android:id="@+id/btnNext"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="下一曲"
android:src="@drawable/ic_next" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>