I have a recyclerview displaying a simple list of items. On long pressing a particular item, a piece of audio associated with this item (stored in the assets folder) is played. On releasing, the audio is paused, and can be returned to at the paused point by long pressing. To that end, I implemented an onTouchListener in the ViewHolder of the RecyclerViews Adapter and created an interface that I call in onBindViewHolder. It works but when I scroll through the items the audio plays automatically and loops endlessly. I can still long press an item and hear its audio playing on top of the automatically looping audio.
I'm not sure where exactly the problem is. I'm not sure if it relates to the way items are recycled in RecyclerView, given it's only something thats an issue when I scroll? I tried to add an onItemTouchListener in the the corresponding fragment and do the work over there but had the same issue.
Or maybe the problem is in how I've set up my onTouchListener and interface? I'm not sure I fully understand what should be happening in onInterceptTouchEvent.
Or does the issue maybe lie in how I've set up my mediaplayer in the onTouchEvent?
public class ClapsAdapter extends RecyclerView.Adapter<ClapsAdapter.ViewHolder> {
List<Clap> mItems;
private Context context;
ItemTouchListener itlistener;
GestureDetector mGestureDetector;
public interface ItemTouchListener {
boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e, List<Clap> list);
void onTouchEvent(List<Clap> list, View view, int position, MotionEvent me);
void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
}
@Override
public long getItemId(int position) {
return position;
}
public ClapsAdapter(Context mContext, List<Clap> myClap) {
super();
this.mItems = myClap;
this.context = mContext;
setHasStableIds(true);
mItems = new ArrayList<Clap>();
Clap mClaps = new Clap();
mClaps.setCName("Hearty Clap");
mClaps.setImageId(R.drawable.clapping1);
mClaps.setAudio("applause-01.mp3");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Business Clap");
mClaps.setImageId(R.drawable.clapping2);
mClaps.setAudio("fake_applause.mp3");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Green Clap");
mClaps.setImageId(R.drawable.clap3);
mClaps.setAudio("laugh_and_applause.mp3");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Slow Clap");
mClaps.setImageId(R.mipmap.slow_clap);
mClaps.setAudio("fake_applause.mp3");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Emoji Clap");
mClaps.setImageId(R.mipmap.clap_emoji);
mClaps.setAudio("light_applause.mp3");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Slow Clap");
mClaps.setImageId(R.mipmap.slow_clap);
mClaps.setAudio("laughter-1.wav");
mItems.add(mClaps);
mClaps = new Clap();
mClaps.setCName("Emoji Clap");
mClaps.setImageId(R.mipmap.clap_emoji);
mClaps.setAudio("laughter-2.mp3");
mItems.add(mClaps);
// this.itlistener = itl;
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnTouchListener{
public TextView title;
public ImageView imageView;
private ItemTouchListener touchListener;
final MediaPlayer mp = new MediaPlayer();
private Context mContext;
List<Clap> mItems;
public ViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.icon);
title = (TextView) itemView.findViewById(R.id.description);
itemView.setTag(itemView);
itemView.setClickable(true);
itemView.setOnTouchListener(this);
}
public void setTouchListener (ItemTouchListener itemTouchListener){
this.touchListener = itemTouchListener;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (touchListener != null) {
touchListener.onTouchEvent(mItems, v, getAdapterPosition(), event);
} return true;
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
//Inflate the layout, initialize the View Holder
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_clap, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Clap clap = mItems.get(position);
holder.title.setText(mItems.get(position).getCName());
holder.imageView.setImageResource(mItems.get(position).getImageId());
final MediaPlayer mp = new MediaPlayer();
holder.setTouchListener(new ItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e, List<Clap> list) {
View childView = rv.findChildViewUnder(e.getX(), e.getY());
if (childView != null && this != null && mGestureDetector.onTouchEvent(e)) {
this.onTouchEvent(list, rv,rv.getChildAdapterPosition(childView), e);
}
return true;
}
@Override
public void onTouchEvent(List<Clap> list, View view, int position, MotionEvent me) {
// Toast.makeText(context, "TOUCH ME!!!",
// Toast.LENGTH_SHORT).show();
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (mp.isPlaying()) {
mp.stop();
mp.release();
}
try {
mp.reset();
AssetFileDescriptor afd;
afd = view.getContext().getAssets().openFd(mItems.get(position).getAudio());
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mp.setLooping(true);
mp.start();
}
break;
case MotionEvent.ACTION_UP: {
mp.pause();
Toast.makeText(context, mItems.get(position).getCName(),
Toast.LENGTH_SHORT).show();
}
break;
}
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
}
@Override
public int getItemCount() {
//returns the number of elements the RecyclerView will display
//return items.size();
return (null != mItems ? mItems.size() : 0);
}
public void insert(int position, Clap clap) {
mItems.add(position, clap);
notifyItemInserted(position);
}
public void remove(Clap clap) {
int position = mItems.indexOf(clap);
mItems.remove(position);
notifyItemRemoved(position);
}
Any help on the matter would be greatly appreciated. I feel like I've spent more time stuck on this than I should!