Kotlin - Воспроизведение аудио с помощью Seekbar в Recyclerview Android - PullRequest
0 голосов
/ 24 июня 2019

Я использую Recyclerview, чтобы показать список аудио-файлов. В каждом элементе списка я использовал Seekbar, чтобы синхронизировать его с состоянием воспроизведения аудио-файла. Теперь проблема заключается в том, что когда я в первый раз нажимаю на значок воспроизведения в любом элементе списка, звук начинает воспроизводиться по желанию, но панель поиска остается без изменений (она не изменяется / не ищет), второй раз работает по желанию (проигрывает аудио, а также ищет панель поиска). Я нашел и попробовал несколько решений из здесь , здесь , но не могу найти подходящее решение.

Вот что у меня есть в классе адаптеров:

class VoiceNotesListAdapter(private val voiceNotesList: ArrayList<VoiceNote>) :
    RecyclerView.Adapter<VoiceNotesListAdapter.ViewHolder>() {

    lateinit var mediaPlayer: MediaPlayer
    private var currentPlayingPosition = -1
    private var seekBarUpdater = SeekBarUpdater()
    private var playingHolder: ViewHolder? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(com.rhythmcor.R.layout.item_voice_notes, parent, false)

        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return voiceNotesList.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        holder.bindVoiceItem(voiceNotesList[position])
        if (position == currentPlayingPosition) {
            playingHolder = holder
            updatePlayingView()
        } else {
            updateNonPlayingView(holder)
        }
    }

    override fun onViewRecycled(holder: ViewHolder) {
        super.onViewRecycled(holder)
        if (currentPlayingPosition == holder.adapterPosition) {
            updateNonPlayingView(playingHolder)
            playingHolder = null
        }
    }

    private fun updateNonPlayingView(holder: ViewHolder?) {
        holder?.seekBarPlayIndicator?.removeCallbacks(seekBarUpdater)
        holder?.seekBarPlayIndicator?.isEnabled = false
        holder?.seekBarPlayIndicator?.progress = 0
        holder?.imgPlayPause?.setImageResource(com.rhythmcor.R.drawable.ic_play_black_24dp)
    }

    private fun updatePlayingView() {
        playingHolder?.seekBarPlayIndicator?.isEnabled = true
        playingHolder?.seekBarPlayIndicator?.max = mediaPlayer.duration
        playingHolder?.seekBarPlayIndicator?.progress = mediaPlayer.currentPosition
    }

    fun stopPlayer() {
        if (null != mediaPlayer) {
            releaseMediaPlayer()
        }
    }

    private inner class SeekBarUpdater : Runnable {
        override fun run() {
            if (null != playingHolder) {
                playingHolder?.seekBarPlayIndicator?.progress = mediaPlayer.currentPosition
                playingHolder?.seekBarPlayIndicator?.postDelayed(this, 100)
            }
        }
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        var imgPlayPause: AppCompatImageView? = null
        var seekBarPlayIndicator: AppCompatSeekBar? = null

        /**
         * Binds/Sets/Updates data to the view-item.
         *
         * @param voiceNote Instance of [VoiceNote] data class to get the data from it and set to
         *              respective view.
         */
        fun bindVoiceItem(voiceNote: VoiceNote) {
            // Find views
            imgPlayPause = itemView.findViewById<AppCompatImageView>(com.rhythmcor.R.id.img_item_voice_note_play_pause)
            seekBarPlayIndicator =
                itemView.findViewById<AppCompatSeekBar>(com.rhythmcor.R.id.seekbar_item_voice_note_play_indicator)

            // Media player instance to find the audio duration.
            val durationMediaPlayer = MediaPlayer()
            durationMediaPlayer.setDataSource(voiceNote.note)
            durationMediaPlayer.prepare()

            // Convert duration from Millisecond format to MM:SS format
            val audioDuration = String.format(
                "%02d : %02d",
                TimeUnit.MILLISECONDS.toMinutes(durationMediaPlayer.duration.toLong()),
                TimeUnit.MILLISECONDS.toSeconds(durationMediaPlayer.duration.toLong()) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(durationMediaPlayer.duration.toLong()))
            )
            durationMediaPlayer.release()

            // Sets Duration text
            itemView.findViewById<AppCompatTextView>(com.rhythmcor.R.id.tv_item_voice_note_duration).text =
                audioDuration

            // Sets Date text
            itemView.findViewById<AppCompatTextView>(com.rhythmcor.R.id.tv_item_voice_note_date).text =
                parseTimestamp(voiceNote.createdOn.toLong() * 1000, DATE_FORMAT_YYYYMMDD_HHMMSS)

            // Set the click listener to delete icon
            itemView.findViewById<AppCompatImageView>(com.rhythmcor.R.id.img_item_voice_note_delete)
                .setOnClickListener {
                    // Publish subject for delete action so their respective subscriber can fetch that event
                    voiceNoteDeleteSubject.onNext(adapterPosition)
                }

            imgPlayPause?.setOnClickListener {

                if (adapterPosition == currentPlayingPosition) {
                    if (mediaPlayer.isPlaying) {
                        mediaPlayer.pause()
                        playingHolder?.seekBarPlayIndicator?.removeCallbacks(seekBarUpdater)
                        playingHolder?.imgPlayPause?.setImageResource(com.rhythmcor.R.drawable.ic_play_black_24dp)
                    } else {
                        mediaPlayer.start()
                        playingHolder?.seekBarPlayIndicator?.postDelayed(seekBarUpdater, 100)
                        playingHolder?.imgPlayPause?.setImageResource(com.rhythmcor.R.drawable.ic_pause_black_24dp)
                    }
                } else {
                    currentPlayingPosition = adapterPosition
                    if (::mediaPlayer.isInitialized && mediaPlayer != null) {
                        if (null != playingHolder) {
                            updateNonPlayingView(playingHolder)
                        }
                        mediaPlayer.release()
                    }
                    playingHolder = this
                    startMediaPlayer(voiceNote.note)
                }
                updatePlayingView()
            }
        }

    }

    private fun startMediaPlayer(audioPath: String) {
        mediaPlayer = MediaPlayer()
        mediaPlayer.setDataSource(audioPath)
        mediaPlayer.setOnPreparedListener {
            mediaPlayer.start()
            playingHolder?.seekBarPlayIndicator?.postDelayed(seekBarUpdater, 100)
            playingHolder?.imgPlayPause?.setImageResource(com.rhythmcor.R.drawable.ic_pause_black_24dp)
        }
        mediaPlayer.setOnErrorListener { mp, what, extra -> true }
        mediaPlayer.prepareAsync()
        mediaPlayer.setOnCompletionListener {

            releaseMediaPlayer()
        }
    }

    private fun releaseMediaPlayer() {
        if (null != playingHolder) {
            updateNonPlayingView(playingHolder)
        }
        mediaPlayer.release()
        currentPlayingPosition = -1
    }
}

Любая помощь будет оценена. Спасибо.

...