简体   繁体   English

片段内的 RecyclerView 不可点击

[英]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.我正在编写一个音乐播放器应用程序,并且由于某种原因 RecyclerView 不可点击并且当我按下一个项目时应用程序刚刚关闭,因此片段内的 RecyclerView 存在问题(它连接到我的主要活动中的选项卡布局)。 Can you please help me with that?你能帮我吗? I added the fragment class and the adapter class.我添加了片段 class 和适配器 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.尝试将holder上的 onClickListener 设置到onBindViewHolder方法中,并且在调用侦听器时需要将其传递到setListener(MusicListener listener)方法中。 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

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 .此外,最好在创建 RecyclerView 适配器时传递MusicListener ,因为您很容易忘记设置它,这将导致Nullpointer Exception

I am not sure why you are doing this: String s = String.valueOf(R.drawable.lionkingposter);我不知道你为什么这样做: 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如果要将 Drawable 资源保留在 class 中,请将可绘制资源设置为setBackgroundResource方法时仅保留R.drawable.lionkingposter

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您需要创建一个implements RecyclerView.OnItemTouchListener的监听器 class

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但在适配器下方 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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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