You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 16:49:56