如何在Recyclview Android上使用带有seekbar的音频? [英] How to use the Audio with seekbar on Recyclview android?

查看:84
本文介绍了如何在Recyclview Android上使用带有seekbar的音频?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Recyclview 上的音频列表,并且工作正常,这意味着我可以在 Recyclview 上播放音频文件.

由于我在 Recyclview 上使用音频文件中的 Seekbar 时,问题是当我滚动 另一个 items's of Recyclview Seekbar 正在更改(我正在使用搜索栏来查看音频文件的播放进度.)

当我滚动 Recyclview 时,我不希望更改 Recyclview 的其他 Seekbar 项的内容

请检查我的代码,在 Recyclview onBindViewHolder 中,我正在使用以下代码,请检查一下.

 ((MyAudioChat) holder).sbMyAudio.setTag(position);
            ((MyAudioChat) holder).imgPlayAudio.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ((MyAudioChat) holder).sbMyAudio.removeCallbacks(null);
                    ((MyAudioChat) holder).sbMyAudio.setProgress(0);
                    if (mediaPlayer == null) {
                        mediaPlayer();
                        ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration());
                    } else {
                        mediaPlayer.stop();
                        mediaPlayer.release();
                        mediaPlayer();
                        ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration());
                    }

                    ((MyAudioChat) holder).sbMyAudio.getTag();
                    ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration()); // Set the Maximum range of the
                    ((MyAudioChat) holder).sbMyAudio.setProgress(mediaPlayer.getCurrentPosition());// set current progress to song's
                    Runnable moveSeekBarThread = new Runnable() {
                        public void run() {
                            if (mediaPlayer.isPlaying()) {

                                int mediaPos_new = mediaPlayer.getCurrentPosition();
                                int mediaMax_new = mediaPlayer.getDuration();
                                ((MyAudioChat) holder).sbMyAudio.setMax(mediaMax_new);
                                ((MyAudioChat) holder).sbMyAudio.setProgress(mediaPos_new);
                                ((MyAudioChat) holder).sbMyAudio.postDelayed(this, 100); //Looping the thread after 0.1 second
                                ((MyAudioChat) holder).sbMyAudio.getTag();
                            }

                        }
                    };

                    ((MyAudioChat) holder).sbMyAudio.removeCallbacks(moveSeekBarThread);
                    ((MyAudioChat) holder).sbMyAudio.postDelayed(moveSeekBarThread, 100);

                }
            });

我在 SO 上访问了以下站点,但未获得相关的解决方案
1.第一链接
2.第二个链接

我们可以使用 setTag() getTag() 摆脱此问题.我在上面的代码中使用了 setTag() .请检查一次.

解决方案

尽管如此,我假设您只询问了正确的SeekBar更新(,因为您没有分片完整的源代码)很快您将面临与Adapter实现相关的以下问题:

  • MediaPlayer完成音频播放后,如何删除seekBar更新程序?
  • 活动暂停后如何释放MediaPlayer?
  • 匿名View.OnClickListenerRunnable每次 onBindViewHolder呼叫中分配.如何减少不必要的分配?

您可以在此处找到完整的工作解决方案- GitHub

以下消息源试图解决所有上述问题.根据您的命名法假定某些数据结构/类.

public class MainActivity extends Activity {

    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        AudioChat audioChats[] = new AudioChat[128];
        rv.setAdapter(new MyAdapter(Arrays.asList(audioChats)));

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (null != mediaPlayer) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyAudioChat> {

        private List<AudioChat> audioChats;
        private int currentPlayingPosition;
        private SeekBarUpdater seekBarUpdater;

        MyAdapter(List<AudioChat> audioChats) {
            this.audioChats = audioChats;
            this.currentPlayingPosition = -1;
            seekBarUpdater = new SeekBarUpdater();
        }

        @Override
        public MyAudioChat onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyAudioChat(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
        }

        @Override
        public void onBindViewHolder(MyAudioChat holder, int position) {
            if (position == currentPlayingPosition) {
                seekBarUpdater.playingHolder = holder;
                holder.sbMyAudio.post(seekBarUpdater);
            } else {
                holder.sbMyAudio.removeCallbacks(seekBarUpdater);
                holder.sbMyAudio.setProgress(0);
            }
        }

        private class SeekBarUpdater implements Runnable {
            MyAudioChat playingHolder;

            @Override
            public void run() {
                if (null != mediaPlayer && playingHolder.getAdapterPosition() == currentPlayingPosition) {
                    playingHolder.sbMyAudio.setMax(mediaPlayer.getDuration());
                    playingHolder.sbMyAudio.setProgress(mediaPlayer.getCurrentPosition());
                    playingHolder.sbMyAudio.postDelayed(this, 100);
                } else {
                    playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                }
            }
        }

        @Override
        public int getItemCount() {
            return audioChats.size();
        }

        class MyAudioChat extends RecyclerView.ViewHolder implements View.OnClickListener {
            SeekBar sbMyAudio;
            ImageView imgPlayAudio;

            MyAudioChat(View itemView) {
                super(itemView);
                imgPlayAudio = (ImageView) itemView.findViewById(R.id.imgPlayAudio);
                imgPlayAudio.setOnClickListener(this);
                sbMyAudio = (SeekBar) itemView.findViewById(R.id.sbMyAudio);
            }

            @Override
            public void onClick(View v) {
                currentPlayingPosition = getAdapterPosition();
                if (mediaPlayer != null) {
                    if (null != seekBarUpdater.playingHolder) {
                        seekBarUpdater.playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                        seekBarUpdater.playingHolder.sbMyAudio.setProgress(0);
                    }
                    mediaPlayer.release();
                }
                seekBarUpdater.playingHolder = this;
                startMediaPlayer();
                sbMyAudio.setMax(mediaPlayer.getDuration());
                sbMyAudio.post(seekBarUpdater);
            }
        }

        private void startMediaPlayer() {
            mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mp3);
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    seekBarUpdater.playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                    seekBarUpdater.playingHolder.sbMyAudio.setProgress(0);
                    mediaPlayer.release();
                    mediaPlayer = null;
                    currentPlayingPosition = -1;
                }
            });
            mediaPlayer.start();
        }
    }

    private class AudioChat {

    }
}

I am using the lists of audio on my Recyclview and it is working correct means I am able to play the audio file on my Recyclview.

As i am using the Seekbar with my audio file on my Recyclview , the problem is generating that when i am scrolling the Recyclview the other items's of Recyclview Seekbar is changing (Seekbar i am using for the progress of the audio file play.)

What i want that other Seekbar item of Recyclview sholud not be change when i scroll the Recyclview

Please check my code for it ,Inside the onBindViewHolder for my Recyclview , i am using the following code, please check it once.

 ((MyAudioChat) holder).sbMyAudio.setTag(position);
            ((MyAudioChat) holder).imgPlayAudio.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ((MyAudioChat) holder).sbMyAudio.removeCallbacks(null);
                    ((MyAudioChat) holder).sbMyAudio.setProgress(0);
                    if (mediaPlayer == null) {
                        mediaPlayer();
                        ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration());
                    } else {
                        mediaPlayer.stop();
                        mediaPlayer.release();
                        mediaPlayer();
                        ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration());
                    }

                    ((MyAudioChat) holder).sbMyAudio.getTag();
                    ((MyAudioChat) holder).sbMyAudio.setMax(mediaPlayer.getDuration()); // Set the Maximum range of the
                    ((MyAudioChat) holder).sbMyAudio.setProgress(mediaPlayer.getCurrentPosition());// set current progress to song's
                    Runnable moveSeekBarThread = new Runnable() {
                        public void run() {
                            if (mediaPlayer.isPlaying()) {

                                int mediaPos_new = mediaPlayer.getCurrentPosition();
                                int mediaMax_new = mediaPlayer.getDuration();
                                ((MyAudioChat) holder).sbMyAudio.setMax(mediaMax_new);
                                ((MyAudioChat) holder).sbMyAudio.setProgress(mediaPos_new);
                                ((MyAudioChat) holder).sbMyAudio.postDelayed(this, 100); //Looping the thread after 0.1 second
                                ((MyAudioChat) holder).sbMyAudio.getTag();
                            }

                        }
                    };

                    ((MyAudioChat) holder).sbMyAudio.removeCallbacks(moveSeekBarThread);
                    ((MyAudioChat) holder).sbMyAudio.postDelayed(moveSeekBarThread, 100);

                }
            });

I have visited the following site on SO but did not get the relevant solution
1 .First Link
2. Second Link

Can we use the setTag() and getTag() to get rid of from this problem. I have used the setTag() on my above code. Please check it once.

解决方案

Although, you have asked only about correct SeekBar updates, I am assuming (because you haven't shard complete source) that soon you will face following issues which are linked to the Adapter implementation:

  • How do I remove the seekBar updater, when MediaPlayer completes the playback of audio?
  • How do I release the MediaPlayer when activity is paused?
  • Anonymous View.OnClickListeners and Runnables are being allocated on every onBindViewHolder call. How do I minimize their unnecessary allocation?

You can find complete working solution here - GitHub

Following source tries to fix all above issues. Certain data structures/classes are assumed based on your nomenclature.

public class MainActivity extends Activity {

    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));
        AudioChat audioChats[] = new AudioChat[128];
        rv.setAdapter(new MyAdapter(Arrays.asList(audioChats)));

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (null != mediaPlayer) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyAudioChat> {

        private List<AudioChat> audioChats;
        private int currentPlayingPosition;
        private SeekBarUpdater seekBarUpdater;

        MyAdapter(List<AudioChat> audioChats) {
            this.audioChats = audioChats;
            this.currentPlayingPosition = -1;
            seekBarUpdater = new SeekBarUpdater();
        }

        @Override
        public MyAudioChat onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyAudioChat(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
        }

        @Override
        public void onBindViewHolder(MyAudioChat holder, int position) {
            if (position == currentPlayingPosition) {
                seekBarUpdater.playingHolder = holder;
                holder.sbMyAudio.post(seekBarUpdater);
            } else {
                holder.sbMyAudio.removeCallbacks(seekBarUpdater);
                holder.sbMyAudio.setProgress(0);
            }
        }

        private class SeekBarUpdater implements Runnable {
            MyAudioChat playingHolder;

            @Override
            public void run() {
                if (null != mediaPlayer && playingHolder.getAdapterPosition() == currentPlayingPosition) {
                    playingHolder.sbMyAudio.setMax(mediaPlayer.getDuration());
                    playingHolder.sbMyAudio.setProgress(mediaPlayer.getCurrentPosition());
                    playingHolder.sbMyAudio.postDelayed(this, 100);
                } else {
                    playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                }
            }
        }

        @Override
        public int getItemCount() {
            return audioChats.size();
        }

        class MyAudioChat extends RecyclerView.ViewHolder implements View.OnClickListener {
            SeekBar sbMyAudio;
            ImageView imgPlayAudio;

            MyAudioChat(View itemView) {
                super(itemView);
                imgPlayAudio = (ImageView) itemView.findViewById(R.id.imgPlayAudio);
                imgPlayAudio.setOnClickListener(this);
                sbMyAudio = (SeekBar) itemView.findViewById(R.id.sbMyAudio);
            }

            @Override
            public void onClick(View v) {
                currentPlayingPosition = getAdapterPosition();
                if (mediaPlayer != null) {
                    if (null != seekBarUpdater.playingHolder) {
                        seekBarUpdater.playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                        seekBarUpdater.playingHolder.sbMyAudio.setProgress(0);
                    }
                    mediaPlayer.release();
                }
                seekBarUpdater.playingHolder = this;
                startMediaPlayer();
                sbMyAudio.setMax(mediaPlayer.getDuration());
                sbMyAudio.post(seekBarUpdater);
            }
        }

        private void startMediaPlayer() {
            mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mp3);
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    seekBarUpdater.playingHolder.sbMyAudio.removeCallbacks(seekBarUpdater);
                    seekBarUpdater.playingHolder.sbMyAudio.setProgress(0);
                    mediaPlayer.release();
                    mediaPlayer = null;
                    currentPlayingPosition = -1;
                }
            });
            mediaPlayer.start();
        }
    }

    private class AudioChat {

    }
}

这篇关于如何在Recyclview Android上使用带有seekbar的音频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆