回收器查看片段内部不可点击



我正在编写一个音乐播放器应用程序,但由于某种原因,RecyclerView在片段(连接到我的主要活动中的选项卡布局)内遇到问题,RecyclerView不可点击,当我按下一个项目时,应用程序刚刚关闭。 你能帮我吗? 我添加了片段类和适配器类。

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;
}
}

尝试将holder上的onClickListener设置为onBindViewHolder方法,当调用侦听器时,需要将其传递到setListener(MusicListener listener)方法中。像这样:

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

在我看来,最好这样更改interface MusicListener

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

并像这样直接返回点击的项目:

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

此外,最好在创建RecyclerView适配器时传递MusicListener,因为您很容易忘记设置它,这将导致Nullpointer Exception

我不确定你为什么要这样做:String s = String.valueOf(R.drawable.lionkingposter);如果要将可绘制资源保留在类中,请在将可绘制资源设置为 ImagesetBackgroundResourceView 时仅保留R.drawable.lionkingposter

我希望这对;)有所帮助

我遇到了同样的问题,不知道实际原因,但我找到了一个可行的解决方案。 您需要创建一个侦听器类,该类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);}
}

然后从创建回收器视图的片段或主活动中调用它

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) {
}
}));

首先,在片段中实现类似这样的接口。

public class SongFragment extends Fragment implements MusicAdapter.MusicListener

其次,重写方法。

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

第三,将视图传递给方法。 但在适配器对象下方

musicAdapter.setListener(this::onItemClick);

这是完整的解决方案。

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
}
}

最新更新