Search code examples
androidandroid-recyclerviewchatandroid-mediaplayer

Recyclerview scrolling when play audio with mediaplayer


I am developing a chat app, this application has the ability to send voice to chat The sound is played correctly, but the problem When I click on the play button, recyclerview scroll to top:

 private void playVoice(Message message, final ImageView playBtn, final SeekBar seekBar, final CfTextView timer) {
    isCurrentMediaPlayer = !isCurrentMediaPlayer;
    if (isCurrentMediaPlayer) {
        try {
            if (mediaPlayer != null) {
                playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
                seekBar.setProgress(0);
                mediaPlayer.stop();
                timerClass.purge();
                timerClass.cancel();
            }
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(message.getVoice().getUrl());
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    if (mp.isPlaying()) {
                        mp.pause();
                        playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
                    } else {
                        mp.start();
                        playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_pause, null));

                    }

                    timer.setText(formatDuration(0));
                    seekBar.setMax(mediaPlayer.getDuration());
                    if (mediaPlayer != null) {
                        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                            @Override
                            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                                if (fromUser) {
                                    mediaPlayer.seekTo(progress);
                                }
                            }

                            @Override
                            public void onStartTrackingTouch(SeekBar seekBar) {

                            }

                            @Override
                            public void onStopTrackingTouch(SeekBar seekBar) {

                            }
                        });
                    }


                    timerClass = new Timer();
                    timerClass.schedule(new MainTimer(timer, seekBar), 0, 1000);
                }
            });

            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    //mediaPlayer = null;
                    //mp.release();
                    timerClass.purge();
                    timerClass.cancel();
                    playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

private class MainTimer extends TimerTask {
    private CfTextView timer;
    private SeekBar seekBar;

    private MainTimer(CfTextView timer, SeekBar seekBar) {
        this.timer = timer;
        this.seekBar = seekBar;
    }

    @Override
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                seekBar.setProgress(mediaPlayer.getCurrentPosition());
                timer.setText(formatDuration(mediaPlayer.getCurrentPosition()));
            }
        });
    }
}

When you click on any play button, the following code runs:

CustomIncomingVoiceMessageViewHolder.Payload payload = new CustomIncomingVoiceMessageViewHolder.Payload();
    payload.onPlayButtonClickListener = new CustomIncomingVoiceMessageViewHolder.onPlayButtonClickListener() {
        @Override
        public void onPlayButtonClick(Message message, final ImageView imageView, final CfTextView timer, final CfTextView time, final SeekBar seekBar) {
            //isCurrentMediaPlayer = !isCurrentMediaPlayer;
            playVoice(message, imageView, seekBar, timer);
        }
    };

my view holder code:

public class CustomIncomingVoiceMessageViewHolder extends MessageHolders.IncomingTextMessageViewHolder<Message> {

private ImageView playButton;
private SeekBar seekBar;
private CfTextView timer;
private CfTextView time;

public CustomIncomingVoiceMessageViewHolder(View itemView, Object payload) {
    super(itemView, payload);
    playButton = itemView.findViewById(R.id.playButton);
    seekBar = itemView.findViewById(R.id.seekBar);
    timer = itemView.findViewById(R.id.timerVoice);
    time = itemView.findViewById(R.id.timeVoice);
}

@Override
public void onBind(final Message message) {
    super.onBind(message);

    final Payload payload = (Payload) this.payload;
    playButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (payload != null && payload.onPlayButtonClickListener != null) {
                payload.onPlayButtonClickListener.onPlayButtonClick(message, playButton, timer, time,seekBar);
            }
        }
    });
}

public static class Payload {
    public onPlayButtonClickListener onPlayButtonClickListener;
}

public interface onPlayButtonClickListener {
    void onPlayButtonClick(Message message, ImageView imageView, CfTextView timer, CfTextView time,SeekBar seekBar);
}

}

i'm using library chatKit

enter image description here


Solution

  • The problem may be due to your layout where you have your "CfTextView timer." I had the same issue and fixed it by setting my Textview width property as follows:

    <TextView
        android:layout_width="match_parent" //This is what I changed
        android:layout_height="wrap_content"/>
    
    <SeekBar
        android:layout_width="match_parent" //Check this as well
        android:layout_height="wrap_content"/>
    

    I can see that in your runnable you have this:

    seekBar.setProgress(mediaPlayer.getCurrentPosition());
    timer.setText(formatDuration(mediaPlayer.getCurrentPosition()));
    

    Here you update the text of your timer to match the mediaPlayer's current position, so if you have the width of your textview to wrap_content it causes your Recyclerview to resize itself.

    Try to apply these changes to your layout and see if it solves the scrolling issues. Best of luck!