[英]RecyclerView inside fragment is not clickable
我正在編寫一個音樂播放器應用程序,並且由於某種原因 RecyclerView 不可點擊並且當我按下一個項目時應用程序剛剛關閉,因此片段內的 RecyclerView 存在問題(它連接到我的主要活動中的選項卡布局)。 你能幫我嗎? 我添加了片段 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;
}
}
嘗試將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);
如果要將 Drawable 資源保留在 class 中,請在將可繪制資源設置為setBackgroundResource
方法時僅保留R.drawable.lionkingposter
我希望這會有所幫助;)
我遇到了同樣的問題,不知道實際原因,但我找到了一個可行的解決方案。 您需要創建一個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);}
}
然后從創建回收器視圖的片段或主要活動中調用它
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) {
}
第三,將視圖傳遞給方法。 但在適配器下方 object
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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.