Android中点击RecyclerView项跳转至对应数组指定位置的实现方法
问题描述
我在Android应用中已实现RecyclerView,且Activity中维护了一个数据数组。现在需要实现点击RecyclerView内的条目时,跳转至数组中对应的指定位置播放歌曲,但不清楚如何将RecyclerView的条目位置与Activity中的数组索引进行同步。
相关代码
MusicPlayer Activity代码
package com.DeepDolphin.narutosongsoffline import android.media.MediaPlayer import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.widget.SeekBar import android.widget.TextView import androidx.core.os.postDelayed import com.DeepDolphin.narutosongsoffline.R import com.DeepDolphin.narutosongsoffline.adapters.seasonOneItems import com.google.android.material.floatingactionbutton.FloatingActionButton class MusicPlayer : AppCompatActivity() { private lateinit var songNameTextView: TextView private lateinit var singerNameTextView: TextView lateinit var playButton :FloatingActionButton lateinit var pauseButton :FloatingActionButton lateinit var stopButton :FloatingActionButton lateinit var songSeekBar: SeekBar private var mediaPlayer : MediaPlayer?= null private var isPlaybackStopped = false private val MusicArray = ArrayList<seasonOneItems>() private var currentIndex = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_music_player) MusicArray.add( seasonOneItems( R.string.opining_one, R.string.singer_one, R.raw.rocks ) ) MusicArray.add( seasonOneItems( R.string.opining_two, R.string.singer_two, R.raw.wind ) ) MusicArray.add( seasonOneItems( R.string.opining_two, R.string.singer_two, R.raw.opning3 ) ) val currentSong = MusicArray[currentIndex] // Initialize views songNameTextView = findViewById(R.id.music_player_song_name) singerNameTextView = findViewById(R.id.music_player_singer_name) playButton = findViewById(R.id.play_button) pauseButton = findViewById(R.id.pause_button) stopButton = findViewById(R.id.stop_button) songSeekBar = findViewById(R.id.song_seek_bar) mediaPlayer = MediaPlayer.create(this, currentSong.song) // Set initial song updateSongData() // Handle button clicks findViewById<TextView>(R.id.previous_song_button).setOnClickListener { playPreviousSong() } findViewById<TextView>(R.id.next_song_button).setOnClickListener { playNextSong() } controlSound(currentIndex) } private fun updateSongData() { val currentSong = MusicArray[currentIndex] songNameTextView.text = getString(currentSong.SongName) singerNameTextView.text = getString(currentSong.SingerName) if (mediaPlayer == null || mediaPlayer?.isPlaying == false) { mediaPlayer = MediaPlayer.create(this, currentSong.song) inisilazeSeekBar() } mediaPlayer?.seekTo(currentIndex) mediaPlayer = MediaPlayer.create(this, currentSong.song) } private fun playPreviousSong() { if (currentIndex > 0) { currentIndex-- mediaPlayer?.stop() mediaPlayer?.reset() mediaPlayer?.release() mediaPlayer = null updateSongData() } } private fun playNextSong() { if (currentIndex < MusicArray.size - 1) { currentIndex++ mediaPlayer?.stop() mediaPlayer?.reset() mediaPlayer?.release() mediaPlayer = null updateSongData() } } override fun onStop() { super.onStop() } fun controlSound(ind:Int) { playButton.setOnClickListener { if (mediaPlayer == null) { mediaPlayer?.start() updateSongData() } mediaPlayer?.start() } pauseButton.setOnClickListener { if (mediaPlayer !== null) mediaPlayer?.pause() } stopButton.setOnClickListener { if (mediaPlayer !== null) { mediaPlayer?.stop() mediaPlayer?.reset() mediaPlayer?.release() mediaPlayer = null } } songSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { if (fromUser == true) mediaPlayer?.seekTo(progress) } override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(seekBar: SeekBar?) {} }) } fun inisilazeSeekBar(){ mediaPlayer?.let { songSeekBar.max = mediaPlayer!!.duration val hander = Handler() hander.postDelayed(object : Runnable { override fun run() { try { songSeekBar.progress = mediaPlayer!!.currentPosition hander.postDelayed(this, 1000) } catch (e: Exception) { songSeekBar.progress = 0 } } },0) } } override fun onPause() { super.onPause() mediaPlayer?.stop() mediaPlayer?.reset() mediaPlayer?.release() mediaPlayer = null } }
SeasonOneAdapter代码
package com.DeepDolphin.narutosongsoffline.adapters import android.content.Intent import android.media.MediaPlayer import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.SeekBar import android.widget.TextView import androidx.cardview.widget.CardView import androidx.recyclerview.widget.RecyclerView import com.DeepDolphin.narutosongsoffline.MusicPlayer import com.DeepDolphin.narutosongsoffline.R import com.google.android.material.floatingactionbutton.FloatingActionButton class SeasonOneAdapter(val SeasonOneArray: ArrayList<seasonOneItems>) : RecyclerView.Adapter<SeasonOneAdapter.SeasonOneViewHolder>() { inner class SeasonOneViewHolder(SeasonOneItem: View) : RecyclerView.ViewHolder(SeasonOneItem) { val SongName = SeasonOneItem.findViewById<TextView>(R.id.song_name) val SingerName = SeasonOneItem.findViewById<TextView>(R.id.singer_name) val seasononecrads = SeasonOneItem.findViewById<CardView>(R.id.season_one_cards) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SeasonOneViewHolder { val view = SeasonOneViewHolder( LayoutInflater.from(parent.context) .inflate(R.layout.music_cell, parent, false) ) return view } override fun getItemCount(): Int { return SeasonOneArray.size } override fun onBindViewHolder(holder: SeasonOneViewHolder, position: Int) { val currentSeasonOneItem = SeasonOneArray[position] holder.SongName.text = holder.itemView.context.getString(SeasonOneArray[position].SongName) holder.SingerName.text = holder.itemView.context.getText(SeasonOneArray[position].SingerName) holder.seasononecrads.setOnClickListener { val arrayindex = SeasonOneArray.lastIndex } } }
解决方案
1. 在Adapter中传递条目索引到MusicPlayer
修改SeasonOneAdapter的点击事件,通过Intent将当前条目的position传递给MusicPlayer:
holder.seasononecrads.setOnClickListener { val intent = Intent(holder.itemView.context, MusicPlayer::class.java) // 传递当前条目索引 intent.putExtra("SELECTED_SONG_INDEX", position) holder.itemView.context.startActivity(intent) }
2. 在MusicPlayer中接收索引并同步播放
修改MusicPlayer的onCreate方法,先获取传递过来的索引,再初始化播放:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_music_player) // 初始化数据数组 MusicArray.add(seasonOneItems(R.string.opining_one, R.string.singer_one, R.raw.rocks)) MusicArray.add(seasonOneItems(R.string.opining_two, R.string.singer_two, R.raw.wind)) MusicArray.add(seasonOneItems(R.string.opining_two, R.string.singer_two, R.raw.opning3)) // 获取从Adapter传递过来的索引,默认0 currentIndex = intent.getIntExtra("SELECTED_SONG_INDEX", 0) val currentSong = MusicArray[currentIndex] // 初始化视图 songNameTextView = findViewById(R.id.music_player_song_name) singerNameTextView = findViewById(R.id.music_player_singer_name) playButton = findViewById(R.id.play_button) pauseButton = findViewById(R.id.pause_button) stopButton = findViewById(R.id.stop_button) songSeekBar = findViewById(R.id.song_seek_bar) mediaPlayer = MediaPlayer.create(this, currentSong.song) // 更新歌曲信息并初始化进度条 updateSongData() inisilazeSeekBar() // 绑定按钮事件 findViewById<TextView>(R.id.previous_song_button).setOnClickListener { playPreviousSong() } findViewById<TextView>(R.id.next_song_button).setOnClickListener { playNextSong() } controlSound(currentIndex) }
3. 修复updateSongData方法的错误
原方法中存在重复创建MediaPlayer的问题,修改为:
private fun updateSongData() { val currentSong = MusicArray[currentIndex] songNameTextView.text = getString(currentSong.SongName) singerNameTextView.text = getString(currentSong.SingerName) // 释放旧的MediaPlayer资源 mediaPlayer?.stop() mediaPlayer?.release() // 创建新的MediaPlayer实例 mediaPlayer = MediaPlayer.create(this, currentSong.song) // 初始化进度条 inisilazeSeekBar() }
4. 优化onPause方法(可选)
原onPause方法直接停止并释放MediaPlayer,会导致回到页面后需要重新点击播放,可改为暂停:
override fun onPause() { super.onPause() mediaPlayer?.pause() } override fun onResume() { super.onResume() mediaPlayer?.start() }
内容的提问来源于stack exchange,提问作者no name
相关产品推荐
相关产品推荐

