0

У меня есть recyclerview, отображающий простой список элементов. При длительном нажатии определенного элемента воспроизводится фрагмент звука, связанный с этим элементом (хранящийся в папке с ресурсами). При отпускании звук приостанавливается и может быть возвращен в паузу, долгое нажатие. С этой целью я реализовал onTouchListener в ViewHolder адаптера RecyclerViews и создал интерфейс, который я вызываю в onBindViewHolder. Он работает, но когда я просматриваю элементы, звук воспроизводится автоматически и циклически бесконечно. Я все еще могу долго нажимать на элемент и слышать его аудиовоспроизведение поверх автоматического аудио цикла.OnTouchEvent постоянно стреляет при прокрутке в RecyclerView

Я не уверен, где именно проблема. Я не уверен, связано ли это с тем, как элементы перерабатываются в RecyclerView, учитывая, что это только проблема, когда я просматриваю? Я попытался добавить onItemTouchListener в соответствующий фрагмент и выполнить работу там, но имел ту же проблему.

Возможно, проблема заключается в том, как я настроил свой onTouchListener и интерфейс? Я не уверен, что полностью понимаю, что должно происходить в onInterceptTouchEvent.

Или может возникнуть проблема в том, как я установил свой медиаплеер в 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); 
} 

Любая помощь по этому вопросу была бы весьма признательна. Мне кажется, что я потратил больше времени на это, чем должен!

ответ

0

вы должны прочитать об управлении сенсорными событиями в группе просмотра http://developer.android.com/training/gestures/viewgroup.html

+0

Спасибо за ответ и жаль, что я не ответил раньше. Я пытался понять, как распространяются события касания - кажется, сложным. Я действительно не понимаю, какую логику я должен писать в onInterceptTouchEvent и что должно быть в onTouchEvent. Я пробовал несколько комбинаций вещей, которые я нашел в Интернете, но поведение по-прежнему остается прежним. Работает так, как ожидалось (звук воспроизводится во время ACTION_DOWN и приостанавливается на ACTION_UP), но когда я просматриваю связанный звук последнего затронутого элемента, он воспроизводится автоматически и в цикле. Будут оценены любые другие рекомендации. –

0

Вы можете прикрепить GestureDetector к вашим onTouchEvent(), а затем написать свою логику в onLongPress().

GestureDetector gestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() { 
     public void onLongPress(MotionEvent e) { 
      //do something here 
     } 
    }); 

    public boolean onTouchEvent(MotionEvent event) { 
     return gestureDetector.onTouchEvent(event); 
    }; 
+0

Спасибо за ответ и жаль, что я не ответил раньше. Пробовал ваш подход, но не был уверен, как ссылаться на позицию и содержание соответствующих элементов? –