0

I want to implement OnClickListener on my songs RecyclerView. whenever i tap on any item, OnClick event is fired, but it gets fired on more than one item. but it should be fired for the item i have tapped. It also gets fired on random rows of RecyclerView. for example when i click on first row of RecyclerView, OnClick event is fired on random positions, say on 7th, 15th, 28th....112th many more. I think it gets recycled so this happens.

At first it was not getting fired on random positions. for example if click on 1st position onclick event got fired on 1st position and also on 12th, 21st, 31st, i.e. on every 12th position. it was periodic but now it just random.

i have tried many methods like:

http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/

https://stackoverflow.com/a/24746411/4754718

I have tried many other methods also but sorry I cant provide link because I need more than 10 reputation for that, sorry.

Following is my viewholder class:

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.TextView;
/**
 * Created by anunay on 7/11/2016.
 */
public class SongsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

    public TextView songName;
    public TextView artistName;
    public TextView songDuration;
    public ImageButton expandChild;
    public Button playNow;
    public Button playNext;
    public Button addToQueue;
    public Button addToPlayList;
    public Button editMetadata;
    public Button delete;
    public static HorizontalScrollView horizontal_scroll;


    public SongsViewHolder(final View itemView) {
        super(itemView);

        songName = (TextView) itemView.findViewById(R.id.songNameText);
        artistName = (TextView) itemView.findViewById(R.id.artistNameText);
        songDuration = (TextView) itemView.findViewById(R.id.songDuration);
        expandChild = (ImageButton) itemView.findViewById(R.id.expandCollapseBtn);
        playNow = (Button) itemView.findViewById(R.id.playNowBtn);
        playNext = (Button) itemView.findViewById(R.id.playNextBtn);
        addToQueue = (Button) itemView.findViewById(R.id.addToQueueBtn);
        addToPlayList = (Button) itemView.findViewById(R.id.addToPlaylistBtn);
        editMetadata = (Button) itemView.findViewById(R.id.editMetaDataBtn);
        delete = (Button) itemView.findViewById(R.id.deleteBtn);
        horizontal_scroll = (HorizontalScrollView) itemView.findViewById(R.id.childSection);

        expandChild.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        horizontal_scroll.setVisibility(View.VISIBLE);
    }
}

and if you like to see , following is my adapter class:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by anunay on 7/11/2016.
 */
public class SongsAdapter extends RecyclerView.Adapter<SongsViewHolder> {

    // private  ArrayList<Song> mSongsArrayList;

    private final List<Song> mSongsArrayList;
    private Context mContext;


    public SongsAdapter(Context context, ArrayList<Song> songsArrayList) {

        mSongsArrayList = songsArrayList;
        mContext = context;

    }

    private Context getContext() {
        return mContext;
    }

    @Override
    public SongsViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        View songsView = inflater.inflate(R.layout.songs_item, parent, false);

       SongsViewHolder songsViewHolder = new SongsViewHolder(songsView);
        return songsViewHolder;
    }

    @Override
    public void onBindViewHolder(final SongsViewHolder holder, int position) {

        Song currSong = mSongsArrayList.get(position);

        TextView songNameText = holder.songName;
        songNameText.setText(currSong.getTitle());
        TextView artistNameText = holder.artistName;
        artistNameText.setText(currSong.getArtist());
        TextView songDurationText = holder.songDuration;

        songDurationText.setText(currSong.getDurationString());
    }

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

}

and this is my screen shot

if i provide a toast in onclick method with position instead of expanding the recyclerview it works perfectly, its neither generated with random position nor periodically.

expandChild.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
              //  horizontal_scroll.setVisibility(View.VISIBLE);

                Toast.makeText(view.getContext(), "clicked at position : "+getAdapterPosition(), Toast.LENGTH_SHORT).show();
            }
        });
Community
  • 1
  • 1
Anunay
  • 1
  • 1
  • 4

2 Answers2

2

put the click listner on the itemView :

public SongsViewHolder(final View itemView) {
    super(itemView);

    songName = (TextView) itemView.findViewById(R.id.songNameText);
    artistName = (TextView) itemView.findViewById(R.id.artistNameText);
    songDuration = (TextView) itemView.findViewById(R.id.songDuration);
    expandChild = (ImageButton) itemView.findViewById(R.id.expandCollapseBtn);
    playNow = (Button) itemView.findViewById(R.id.playNowBtn);
    playNext = (Button) itemView.findViewById(R.id.playNextBtn);
    addToQueue = (Button) itemView.findViewById(R.id.addToQueueBtn);
    addToPlayList = (Button) itemView.findViewById(R.id.addToPlaylistBtn);
    editMetadata = (Button) itemView.findViewById(R.id.editMetaDataBtn);
    delete = (Button) itemView.findViewById(R.id.deleteBtn);
    horizontal_scroll = (HorizontalScrollView) itemView.findViewById(R.id.childSection);

    //expandChild.setOnClickListener(this);

    itemView.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                //any code here
            }
        });


}
henrybbosa
  • 1,083
  • 10
  • 27
  • both methods are same nothing changes whether i use expandChild.setOnClickListener(this) or itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //any code here } }); i have tried this method also. – Anunay Jul 19 '16 at 08:56
0

Try this:

  • Create a Listener for items click in view holder.

        public interface ListItemListener {
    
           void onButtonClick(String anyValue); // parameter is optional. If you want to get any value on its implementation then use.
        }
    
  • Use this listener in your RecyclerView Adapter in constructor.

           private ListItemListener mItemListener;
    
           // Constructor
            public YuueRecyclerViewAdapter(List<Data> mData, RecentItemListener itemListener) {
    
               this.data = mData;
               mItemListener = itemListener;
            }
    
  • Use this in View Holder

    public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
                     @Nullable
    @BindView(R.id.recent_title)
    TextView titleTextView;
    
    public ItemViewHolder(View itemView, ListItemListener listener) {
        super(itemView);
        ButterKnife.bind(this, itemView);
        mItemListener = listener;
        titleTextView.setOnClickListener(this);
    }
    
     @Override
    public void onClick(View v) {
          mItemListener.onButtonClick(mData); // mData is sent if you have any parameter there.
    }
    

OnCreateViewHolder

      @Override
     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
           context = parent.getContext();
           LayoutInflater inflater = LayoutInflater.from(context);
           View progressView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_loading_item, parent, false);
           return new ItemViewHolder(view, mItemListener);

      }
  • Implement this listener on your activity/fragment where you are using RecyclerView.
Ashish Tiwari
  • 1,881
  • 2
  • 25
  • 49
  • i have tried this method also from an answer from stackoverflow, but it didn't worked. After you suggested i tried again but didn't worked. – Anunay Jul 19 '16 at 08:49
  • this has one more problem that it throws Null pointer exception while accessing a particular view of recyclerview from fragment even though i binded that view in my fragment – Anunay Jul 19 '16 at 08:52
  • i have edited my question somewhat, please take a look at last point – Anunay Jul 19 '16 at 09:34