任务一 实现 MV 页面与页面跳转
单元二已经在歌曲列表中预留了 MV 图标。本任务先搭建视频页面并接通跳转,再补上歌曲信息和返回按钮。
一、任务目标
任务结束后,应用将能够:
- 从歌曲列表的 MV 图标进入
VideoActivity。 - 使用
Intent传递 MV 地址、歌曲名称和歌手信息。 - 在视频页面显示歌曲信息,并通过返回按钮回到列表。
- 没有 MV 地址时不打开视频页面。
二、创建视频页面
1. 创建视频页面布局
在 app/src/main/res/layout 下新建 activity_video.xml,先用黑色 ConstraintLayout 和 FrameLayout 搭出视频页面的基本框架。项目已启用 ViewBinding,创建并同步布局后会生成 ActivityVideoBinding。后续任务会在视频容器中加入播放器。
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/black">
<!-- 视频容器,后续将在此处放入播放器。 --> <FrameLayout android:id="@+id/video_container" android:layout_width="0dp" android:layout_height="0dp" android:background="@android:color/black" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>2. 创建 VideoActivity 并接收页面数据
在 app/src/main/java/com/sziit/musicplayer/ui/activity 下新建 VideoActivity.kt。Activity 先加载刚创建的布局,并从 Intent 中读取 MV 地址、歌曲名称和歌手,暂存在成员变量中,供后续页面显示和视频播放使用。
package com.sziit.musicplayer.ui.activity
import android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport com.sziit.musicplayer.databinding.ActivityVideoBinding
class VideoActivity : AppCompatActivity() { private lateinit var binding: ActivityVideoBinding // 保存列表页传来的数据,供后续页面显示和视频播放使用。 private var mvUrl = "" private var songName = "" private var singerName = ""
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 加载视频页面布局。 binding = ActivityVideoBinding.inflate(layoutInflater) setContentView(binding.root)
// 读取列表页通过 Intent 传来的信息。 mvUrl = intent.getStringExtra(EXTRA_MV).orEmpty() songName = intent.getStringExtra(EXTRA_SONG).orEmpty() singerName = intent.getStringExtra(EXTRA_SINGER).orEmpty() }
// 集中定义 Intent 使用的键名,保证传递和读取时使用相同的名称。 companion object { const val EXTRA_MV = "mv" const val EXTRA_SONG = "song" const val EXTRA_SINGER = "singer" }}ActivityVideoBinding 会在布局文件创建后生成。若编辑器暂时提示找不到它,等待项目完成同步即可。
3. 注册 VideoActivity
打开 app/src/main/AndroidManifest.xml,在 <application> 标签内注册 VideoActivity。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> ... <application ...> ... <activity android:name=".ui.activity.VideoActivity" /> ... </application></manifest>三、从歌曲列表打开视频页面
1. 设置 MV 图标的点击操作
打开 MusicListFragment.kt,把适配器的 MV 点击回调交给 openMv(),并在该方法中检查地址、传递数据和打开页面。
// ... 省略已有导入。import android.content.Intentimport android.widget.Toastimport com.sziit.musicplayer.ui.activity.VideoActivity
class MusicListFragment : Fragment() { // ... 省略已有字段和其他方法。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // ... 省略 RecyclerView 初始化代码。 adapter = MusicListAdapter( onMusicClick = { song -> playSong(song) }, onMvClick = {} onMvClick = { song -> openMv(song) } ) // ... 省略 RecyclerView 后续设置代码。 }
private fun openMv(song: Song) { // 没有 MV 地址时提示用户,并结束跳转。 if (song.mvPath.isNullOrEmpty()) { Toast.makeText(requireContext(), "该歌曲没有视频", Toast.LENGTH_SHORT).show() return }
// 将 MV 地址和歌曲信息传给 VideoActivity。 val intent = Intent(requireContext(), VideoActivity::class.java).apply { putExtra(VideoActivity.EXTRA_MV, song.mvPath) putExtra(VideoActivity.EXTRA_SONG, song.name) putExtra(VideoActivity.EXTRA_SINGER, song.singer) } startActivity(intent) }}2. 验证页面跳转
运行应用,点击有 MV 地址的歌曲图标,确认能打开黑色的视频页面;按设备的系统返回键,确认回到歌曲列表。没有 MV 地址的歌曲不会显示 MV 图标;跳转方法也会检查地址,避免打开空页面。
此时视频页面还没有歌曲信息和页面内的返回按钮,下一部分会继续添加。
四、完善视频页面布局
1. 添加歌曲信息和返回按钮
在 activity_video.xml 的视频容器之后添加返回按钮、歌曲名称和歌手控件。返回图标使用初始工程中的 ic_back,并设置白色 tint,使它在黑色背景上清晰可见。
<androidx.constraintlayout.widget.ConstraintLayout ...> ... <!-- 返回按钮显示在页面左上角。 --> <ImageView android:id="@+id/img_back" android:layout_width="56dp" android:layout_height="56dp" android:contentDescription="返回" android:padding="12dp" android:src="@drawable/ic_back" app:tint="@android:color/white" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<!-- 歌曲名称显示在页面左下角。 --> <TextView android:id="@+id/tv_song" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginBottom="4dp" android:textColor="@android:color/white" android:textSize="22sp" android:textStyle="bold" app:layout_constraintBottom_toTopOf="@id/tv_singer" app:layout_constraintStart_toStartOf="parent" />
<!-- 歌手显示在歌曲名称下方。 --> <TextView android:id="@+id/tv_singer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginBottom="16dp" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>2. 显示歌曲信息并设置返回操作
回到 VideoActivity.kt,在 onCreate() 中将已接收的歌曲信息写入控件,并设置返回按钮关闭当前页面。
class VideoActivity : AppCompatActivity() { // ... 省略已有字段和其他代码。
override fun onCreate(savedInstanceState: Bundle?) { // ... 省略 super.onCreate()、布局加载和 Intent 数据读取。
// 将收到的歌曲信息显示在页面上。 binding.tvSong.text = songName binding.tvSinger.text = singerName // 点击后关闭视频页面,返回歌曲列表。 binding.imgBack.setOnClickListener { finish() } }
// ... 省略 companion object。}3. 验证视频页面
再次运行应用,点击有 MV 地址的歌曲图标,确认页面显示歌曲名称、歌手和左上角的返回按钮;点击返回按钮,确认回到歌曲列表。
任务小结
本任务先搭建了视频页面并接通列表跳转,再补充歌曲信息和返回操作。列表页通过 Intent 传递 MV 地址、歌曲名称和歌手,VideoActivity 接收并显示这些数据。下一任务将在视频容器中接入 ExoPlayer。