简体   繁体   中英

RecyclerView inside fragment is not clickable

I am programming a music player app and having a problem with a RecyclerView inside a fragment(which connects to tab layout in my main activity) from some reason the RecyclerView is not clickable and when I am pressing an item the app just close. Can you please help me with that? I added the fragment class and the adapter class.

public class MusicAdapter extends RecyclerView.Adapter<MusicAdapter.MusicviewHolder> {
    private List<Music> songs;
    public Resources res;
    Context context;

    public MusicAdapter(Context context, List<Music> songs) {

        String s = String.valueOf(R.drawable.lionkingposter);
      
        songs.add(new Music("jgggug", "Circle of life", "Alton John ", "Lion King",s));

//        }

        this.songs = songs;//constructor
        this.context=context;
    }

    interface MusicListener {
        void onMusicClicked(int position, View view);

      //  void onDeleteClicked(int position);
    }

    MusicListener listener;

    public void setListener(MusicListener listener) {
        this.listener = listener;
    }

    @Override
    public MusicviewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//function design the cell

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell, parent, false);

        MusicviewHolder musicviewholder = new MusicviewHolder(view);
        return musicviewholder;
    }

    @Override
    public void onBindViewHolder(MusicviewHolder holder, int position) {//this function takes the object and put it in the cell
        Music music = songs.get(position);

        if (music.getPhoto() != null) {
            try {
                holder.songImg.setImageResource(Integer.parseInt(music.getPhoto()));
            } catch (Exception e) {
                //holder.songImg.setImageURI(Uri.parse(music.getPhoto()));
                byte[] decodedString = Base64.decode(music.getPhoto(), Base64.DEFAULT);
                Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
                holder.songImg.setImageBitmap(decodedByte);
            }
        } else {
            holder.songImg.setImageResource(0);

        }

        holder.songName.setText(music.getTitle());
        holder.movieName.setText(music.getAlbum());
     holder.itemView.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
              // Intent intent=new Intent(context,MediaPlayer.class);
               //intent.putExtra("song",position);
              //context.startActivity(intent);
               Toast.makeText(context,"hello",Toast.LENGTH_SHORT);
           }
       });

    }

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

    public class MusicviewHolder extends RecyclerView.ViewHolder {

        TextView songName;
        TextView movieName;
        ImageView songImg;

        public MusicviewHolder(@NonNull View itemView) {
            super(itemView);
            songName = itemView.findViewById(R.id.song_title);
            movieName = itemView.findViewById(R.id.movie_title);
            songImg = itemView.findViewById(R.id.song_img);
            itemView.setOnClickListener(new View.OnClickListener() {
                                            @Override
                                            public void onClick(View v) {
                                                if (listener != null)
                                                    listener.onMusicClicked(getAdapterPosition(), v);
                                            }
                                        }
            );
        }
    }

}

public class SongFragment extends Fragment {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    private RecyclerView recyclerview;
    private RecyclerView.Adapter myadapter;
    private RecyclerView.LayoutManager layoutManager;
    View view;
    private ArrayList<Music> songs=new ArrayList<>();
    private Resources res;
    public Context context;
    Bundle bundle;

    //  private ShowSongActivity show;
    public SongFragment() {

        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment SongsFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static SongFragment newInstance(String param1, String param2) {
        SongFragment fragment = new SongFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);


        }

        ArrayList<Music> listTemp = MusicManager.getInstance(getContext()).getMusics();

        if (listTemp != null)
            songs.addAll((Collection<? extends Music>) listTemp.clone());

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       
        View view = inflater.inflate(R.layout.fragment_songs, container, false);
        recyclerview = (RecyclerView) view.findViewById(R.id.songs_recycler);

        MusicAdapter musicAdapter = new MusicAdapter(context,songs);
        recyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerview.setAdapter(musicAdapter);
        recyclerview.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));

        return view;
    }
}

Try to set onClickListener on the holder into the onBindViewHolder method and when invoke the listener it need to be passed into the setListener(MusicListener listener) method. Something like this:

 holder.itemView.setOnClickListener(v -> this.listener.onMusicClicked(position, v);});

In my opinion, it's better to change the interface MusicListener like that:

interface MusicListener {
        void onMusicClicked(int position, Music item);
}

And return the clicked item directly like this:

 holder.itemView.setOnClickListener(v -> this.listener.onMusicClicked(position, songs.get(position);});

Furthermore, it is better to pass the MusicListener when you create the RecyclerView Adapter because you can easily forget to set it and this will cause the Nullpointer Exception .

I am not sure why you are doing this: String s = String.valueOf(R.drawable.lionkingposter); If you want to keep the Drawable resource in the class make property int (Integer) and keep only the R.drawable.lionkingposter when you set the drawable resource to an ImageView use setBackgroundResource method as described here

I hope this helped;)

I faced the same problem, Don't know the actual cause of this but I found a working solution. You need to create a Listener class which implements RecyclerView.OnItemTouchListener

public class MatchClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;

public MatchClickListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
    this.clickListener = clickListener;
    gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null) {
                clickListener.onLongClick(child, recyclerView.getChildPosition(child));
            }
        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

    View child = rv.findChildViewUnder(e.getX(), e.getY());
    if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
        clickListener.onClick(child, rv.getChildPosition(child));
    }
    return false;
}

@Override
public void onTouchEvent(@NotNull RecyclerView rv, MotionEvent e) {
}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

public interface ClickListener {
    void onClick(View view, int position);

    void onLongClick(View view, int position);}
}

Then call it from your fragment or mainactivity where recyler view is created

recyclerView.addOnItemTouchListener(new MatchClickListener
                (getActivity(),recyclerView, new MatchClickListener.ClickListener() {
                    @Override
                    public void onClick(View view, int position) {
                        Intent in =new Intent(getActivity(), TournamentPage.class);
                      
                        startActivity(in);
                    }

                    @Override
                    public void onLongClick(View view, int position) {

                    }
                }));

First, implement the interface in fragment something like that.

public class SongFragment extends Fragment implements MusicAdapter.MusicListener

Second, override the method.

@Override
    public void onMusicClicked(int position, View view) {
}

Third, Pass the view to the method. but below the adapter object

musicAdapter.setListener(this::onItemClick);

Here is the complete solution.

public class SongFragment extends Fragment implements MusicAdapter.MusicListener {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    private RecyclerView recyclerview;
    private RecyclerView.Adapter myadapter;
    private RecyclerView.LayoutManager layoutManager;
    View view;
    private ArrayList<Music> songs=new ArrayList<>();
    private Resources res;
    public Context context;
    Bundle bundle;

    //  private ShowSongActivity show;
    public SongFragment() {

        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment SongsFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static SongFragment newInstance(String param1, String param2) {
        SongFragment fragment = new SongFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);


        }

        ArrayList<Music> listTemp = MusicManager.getInstance(getContext()).getMusics();

        if (listTemp != null)
            songs.addAll((Collection<? extends Music>) listTemp.clone());

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       
        View view = inflater.inflate(R.layout.fragment_songs, container, false);
        recyclerview = (RecyclerView) view.findViewById(R.id.songs_recycler);

        MusicAdapter musicAdapter = new MusicAdapter(context,songs);
        recyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerview.setAdapter(musicAdapter);
        recyclerview.setLayoutManager(new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false));
musicAdapter.setListener(this::onItemClick);

        return view;
    }
@Override
        public void onMusicClicked(int position, View view) {
          // here implement which you want
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM