Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin-在Recyclerview Android中使用Seekbar播放音频_Android_Kotlin_Android Mediaplayer_Android Recyclerview_Android Seekbar - Fatal编程技术网

Kotlin-在Recyclerview Android中使用Seekbar播放音频

Kotlin-在Recyclerview Android中使用Seekbar播放音频,android,kotlin,android-mediaplayer,android-recyclerview,android-seekbar,Android,Kotlin,Android Mediaplayer,Android Recyclerview,Android Seekbar,我正在使用Recyclerview显示音频文件列表。在每个列表项中,我都使用Seekbar将其与音频文件的播放状态同步。现在的问题是,当我第一次点击任何列表项中的播放图标时,音频开始按需播放,但seekbar保持原样(未更改/搜索),第二次按需工作(播放音频并搜索搜索栏)。我在谷歌上搜索并尝试了几个解决方案,但找不到相关的解决方案 以下是我的适配器类中的内容: class VoiceNotesListAdapter(private val voiceNotesList: ArrayList<

我正在使用
Recyclerview
显示音频文件列表。在每个列表项中,我都使用
Seekbar
将其与音频文件的播放状态同步。现在的问题是,当我第一次点击任何列表项中的播放图标时,音频开始按需播放,但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
    }
}
class VoiceNotesListAdapter(私有val voiceNotesList:ArrayList):
RecyclerView.Adapter(){
lateinit var mediaPlayer:mediaPlayer
私有变量currentPlayingPosition=-1
私有变量seekBarUpdater=seekBarUpdater()
private var playingHolder:视图持有者?=null
override onCreateViewHolder(父级:ViewGroup,viewType:Int):ViewHolder{
val view=LayoutInflater.from(parent.context)
.充气(com.hyrthmcor.R.layout.item\u voice\u notes,父项,假)
返回视图保持器(视图)
}
重写getItemCount():Int{
返回voiceNotesList.size
}
覆盖BindViewHolder(holder:ViewHolder,位置:Int){
holder.bindVoiceItem(voiceNotesList[位置])
如果(位置==当前播放位置){
playingHolder=保持架
updatePlayingView()
}否则{
updateNonPlayingView(支架)
}
}
覆盖视图(保持架:视图保持架){
super.onViewRecycled(支架)
if(currentPlayingPosition==支架适配器位置){
updateNonPlayingView(播放文件夹)
playingHolder=null
}
}
私人娱乐更新NonPlayingView(持有者:ViewHolder?){
支架?参见kbarplayindicator?拆下Callbacks(参见kbarUpdater)
保持架?.seekBarPlayIndicator?.isEnabled=错误
保持架?.seekBarPlayIndicator?.progress=0
holder?.imgPlayPause?.setImageResource(com.hyrthcor.R.drawable.ic\u play\u black\u 24dp)
}
private fun updatePlayingView(){
playingHolder?.seekBarPlayIndicator?.isEnabled=真
playingHolder?.seekBarPlayIndicator?.max=mediaPlayer.duration
playingHolder?.seekBarPlayIndicator?.progress=mediaPlayer.currentPosition
}
趣味图层(){
如果(空!=mediaPlayer){
releaseMediaPlayer()
}
}
私有内部类SeekBarUpdater:Runnable{
覆盖趣味跑(){
如果(null!=播放文件夹){
playingHolder?.seekBarPlayIndicator?.progress=mediaPlayer.currentPosition
playingHolder?.seekBarPlayIndicator?.postDelayed(此,100)
}
}
}
内部类ViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
var imgPlayPause:AppCompatImageView?=null
var seekBarPlayIndicator:AppCompatSeekBar?=null
/**
*将数据绑定/设置/更新到视图项。
*
*[voiceNote]数据类的@param voiceNote实例,从中获取数据并设置为
*各自的观点。
*/
趣味bindVoiceItem(voiceNote:voiceNote){
//查找视图
imgPlayPause=itemView.findViewById(com.hyrthcor.R.id.img\u item\u voice\u note\u play\u pause)
Seekbarplay指示器=
itemView.findViewById(com.rhythcor.R.id.seekbar\u项目\语音\音符\播放\指示器)
//Media player实例以查找音频持续时间。
val durationMediaPlayer=MediaPlayer()
durationMediaPlayer.setDataSource(voiceNote.note)
durationMediaPlayer.prepare()
//将持续时间从毫秒格式转换为MM:SS格式
val audioDuration=String.format(
“%02d:%02d”,
TimeUnit.millides.toMinutes(durationMediaPlayer.duration.toLong()),
TimeUnit.millides.toSeconds(durationMediaPlayer.duration.toLong())-
TimeUnit.MINUTES.toSeconds(TimeUnit.millides.toMinutes(durationMediaPlayer.duration.toLong()))
)
durationMediaPlayer.release()
//设置持续时间文本
itemView.findViewById(com.rhythcor.R.id.tv\u item\u voice\u note\u duration)。文本=
听力时长
//设置日期文本
itemView.findViewById(com.rhythcor.R.id.tv\u item\u voice\u note\u date)。文本=
parseTimestamp(voiceNote.createdOn.toLong()*1000,日期格式为YYYYMMDD\uHHMMSS)
//设置“单击侦听器以删除”图标
itemView.findViewById(com.hyrthcor.R.id.img\u项目\u语音\u注释\u删除)
.setOnClickListener{
//发布删除操作的主题,以便其各自的订阅者可以获取该事件
voiceNoteDeleteSubject.onNext(适配器位置)
}
imgPlayPause?.setOnClickListener{
if(适配器位置==当前播放位置){
如果(mediaPlayer.isplay){
mediaPlayer.pause()
playingHolder?.seekBarPlayIndicator?.removeCallbacks(请参阅播放时间)
playingHolder?.imgPlayPause?.setImageResource(com.rhythcor.R.drawable.ic_play_black_24dp)
}否则{
mediaPlayer.start()
播放文件夹?.seekBarPlayIndicator?.postDelayed(请参阅播放日期,100)
playingHolder?.imgPlayPause?.setImageResource(com.rhythcor.R.drawable.ic_pause_black_24dp)
}
}否则{
当前播放位置=适配器位置
如果(::mediaPlayer.isInitialized&&mediaPlayer!=null){
如果(null!=播放文件夹){