I need some help, I want to make a recycle view containing audio in each item, how to play the audio when press play button and set progress to seekbar and at the same time pause other sound and convert the play button to play mode in all row except the playing one be in pause mode such as or chats in facebook messenger
This is my code: MyAdapter.class
private List<String> positions = new ArrayList<>();
public myAdapter(Activity activity, ArrayList<Tweet> list) {
this.activity = activity;
this.list = list;
mPlayer = new MediaPlayer();
}
public void onBindViewHolder(final viewHolder holder, final int position) {
if (!positions.contains(String.valueOf(position)))
positions.add(String.valueOf(position));
}
}
viewHolder.class
public class viewHolder extends RecyclerView.ViewHolder implements
SeekBar.OnSeekBarChangeListener, View.OnClickListener {
LinearLayout parentPanel;
int viewType;
private RelativeLayout pauseLayout, playLayout;
private ImageView pauseIcon, playIcon;
private SeekBar seekBar;
private TextView periodTime;
AudioCallbacks mAudioCallbacks;
private int last_position;
viewHolder(final View itemView, int viewType) {
super(itemView);
this.viewType = viewType;
playLayout = (RelativeLayout) itemView.findViewById(R.id.play_layout);
pauseLayout = (RelativeLayout) itemView.findViewById(R.id.pause_layout);
playIcon = (ImageView) itemView.findViewById(R.id.play_icon);
pauseIcon = (ImageView) itemView.findViewById(R.id.pause_icon);
seekBar = (SeekBar) itemView.findViewById(R.id.seekBar);
periodTime = (TextView) itemView.findViewById(R.id.period_time);
seekBar.setOnSeekBarChangeListener(this);
playLayout.setOnClickListener(this);
pauseLayout.setOnClickListener(this);
mAudioCallbacks = new AudioCallbacks() {
@Override
public void onUpdate(int percentage) {
seekBar.setProgress(percentage);
if (percentage == 100)
mAudioCallbacks.onStop();
}
@Override
public void onPause() {
Log.i("on pause audio", " pause");
}
@Override
public void onStop() {
Log.i("on stop audio", " stop");
stopPlayingAudio();
}
};
}
void stopPlayingAudio() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
updateAudioProgressBar();
mPlayer.stop();
mPlayer.reset();
seekBar.setProgress(0);
playLayout.setVisibility(View.VISIBLE);
pauseLayout.setVisibility(View.GONE);
}
}
}
void pausePlayingAudio() {
if (mPlayer != null) {
if (mPlayer.isPlaying()) {
mPlayer.pause();
updateAudioProgressBar();
mAudioCallbacks.onPause();
}
}
}
void playingAudio(Tweet message) {
updateAudioProgressBar();
if (mPlayer != null) {
try {
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(message.getAudioUrl());
mPlayer.prepare();
mPlayer.start();
periodTime.setVisibility(View.VISIBLE);
periodTime.setText(String.valueOf(message.getAudioDuration()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
void updateAudioProgressBar() {
durationHandler.postDelayed(mUpdateTimeTask, 100);
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
try {
if (mPlayer.isPlaying()) {
long totalDuration = mPlayer.getDuration();
long currentDuration = mPlayer.getCurrentPosition();
int progress = Utils.getProgressPercentage(currentDuration, totalDuration);
mAudioCallbacks.onUpdate(progress);
periodTime.setText(Utils.getFileTime(currentDuration));
durationHandler.postDelayed(this, 100);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
durationHandler.removeCallbacks(mUpdateTimeTask);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int totalDuration = mPlayer.getDuration();
int currentPosition = Utils.progressToTimer(seekBar.getProgress(), totalDuration);
mPlayer.seekTo(currentPosition);
updateAudioProgressBar();
}
@Override
public void onClick(View view) {
Log.e("getAdapterPosition()L", last_position + " /");
for (String pos : positions) {
if (!pos.equals(String.valueOf(getAdapterPosition())))
notifyItemChanged(Integer.parseInt(pos));
}
last_position = getAdapterPosition();
Log.e("getAdapterPosition()F", last_position + " /");
Tweet message = list.get(getAdapterPosition());
switch (view.getId()) {
case R.id.pause_layout:
playLayout.setVisibility(View.VISIBLE);
pauseLayout.setVisibility(View.GONE);
pausePlayingAudio();
break;
case R.id.play_layout:
playLayout.setVisibility(View.GONE);
pauseLayout.setVisibility(View.VISIBLE);
mAudioCallbacks.onStop();
playingAudio(message);
break;
}
}
}
public interface AudioCallbacks {
void onUpdate(int percentage);
void onPause();
void onStop();
}
the problem of this code is :
Can someone helped me, please?
Controlling and updating progress of MediaPlayer
from RecyclerView
cells is tricky. Your solution does not correctly update the view states in onBindViewHolder
call, which is the root cause of all the issues you are facing. Few other notes one should keep in mind are as follows:
xxxListener
s, Runnable
s in onBindViewHolder
, i.e. ViewHolder
can be used to implement xxxListener
interfaces etc.Below source shows possible implementation of Adapter
private class AudioItemAdapter extends RecyclerView.Adapter<AudioItemAdapter.AudioItemsViewHolder> {
private MediaPlayer mediaPlayer;
private List<AudioItem> audioItems;
private int currentPlayingPosition;
private SeekBarUpdater seekBarUpdater;
private AudioItemsViewHolder playingHolder;
AudioItemAdapter(List<AudioItem> audioItems) {
this.audioItems = audioItems;
this.currentPlayingPosition = -1;
seekBarUpdater = new SeekBarUpdater();
}
@Override
public AudioItemsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new AudioItemsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
}
@Override
public void onBindViewHolder(AudioItemsViewHolder holder, int position) {
if (position == currentPlayingPosition) {
playingHolder = holder;
updatePlayingView();
} else {
updateNonPlayingView(holder);
}
}
@Override
public void onViewRecycled(AudioItemsViewHolder holder) {
super.onViewRecycled(holder);
if (currentPlayingPosition == holder.getAdapterPosition()) {
updateNonPlayingView(playingHolder);
playingHolder = null;
}
}
private void updateNonPlayingView(AudioItemsViewHolder holder) {
holder.sbProgress.removeCallbacks(seekBarUpdater);
holder.sbProgress.setEnabled(false);
holder.sbProgress.setProgress(0);
holder.ivPlayPause.setImageResource(R.drawable.ic_play_arrow);
}
private void updatePlayingView() {
playingHolder.sbProgress.setMax(mediaPlayer.getDuration());
playingHolder.sbProgress.setProgress(mediaPlayer.getCurrentPosition());
playingHolder.sbProgress.setEnabled(true);
if (mediaPlayer.isPlaying()) {
playingHolder.sbProgress.postDelayed(seekBarUpdater, 100);
playingHolder.ivPlayPause.setImageResource(R.drawable.ic_pause);
} else {
playingHolder.sbProgress.removeCallbacks(seekBarUpdater);
playingHolder.ivPlayPause.setImageResource(R.drawable.ic_play_arrow);
}
}
void stopPlayer() {
if (null != mediaPlayer) {
releaseMediaPlayer();
}
}
private class SeekBarUpdater implements Runnable {
@Override
public void run() {
if (null != playingHolder) {
playingHolder.sbProgress.setProgress(mediaPlayer.getCurrentPosition());
playingHolder.sbProgress.postDelayed(this, 100);
}
}
}
@Override
public int getItemCount() {
return audioItems.size();
}
class AudioItemsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, SeekBar.OnSeekBarChangeListener {
SeekBar sbProgress;
ImageView ivPlayPause;
AudioItemsViewHolder(View itemView) {
super(itemView);
ivPlayPause = (ImageView) itemView.findViewById(R.id.ivPlayPause);
ivPlayPause.setOnClickListener(this);
sbProgress = (SeekBar) itemView.findViewById(R.id.sbProgress);
sbProgress.setOnSeekBarChangeListener(this);
}
@Override
public void onClick(View v) {
if (getAdapterPosition() == currentPlayingPosition) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
} else {
currentPlayingPosition = getAdapterPosition();
if (mediaPlayer != null) {
if (null != playingHolder) {
updateNonPlayingView(playingHolder);
}
mediaPlayer.release();
}
playingHolder = this;
startMediaPlayer(audioItems.get(currentPlayingPosition).audioResId);
}
updatePlayingView();
}
@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) {
}
}
private void startMediaPlayer(int audioResId) {
mediaPlayer = MediaPlayer.create(getApplicationContext(), audioResId);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
releaseMediaPlayer();
}
});
mediaPlayer.start();
}
private void releaseMediaPlayer() {
if (null != playingHolder) {
updateNonPlayingView(playingHolder);
}
mediaPlayer.release();
mediaPlayer = null;
currentPlayingPosition = -1;
}
}
You can find complete working solution here - GitHub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With