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
}
}
Related
I'm doing my final project that due tomorrow and I only have one thing left to do. But I already lost a lot of time on it. I am creating a recyclerview from a JSON that I obtain through Volley from the Adafruit API and everything is fine, the only thing i need is that when I clicking on the items different Intents are opened. I would greatly appreciate if someone could help me. I have to say that I am working on a fragment and there things are a little different.
The code of my Adapter:
public class AdafruitFeedAdapter extends RecyclerView.Adapter<AdafruitFeedAdapter.viewholder> {
ArrayList<FeedData> feedData;
public AdafruitFeedAdapter(ArrayList<FeedData> feedData) {
this.feedData = feedData;
}
#NonNull
#Override
public viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feed, parent, false);
return new viewholder(v);
}
#Override
public void onBindViewHolder(#NonNull viewholder holder, int position) {
holder.setData(feedData.get(position));
}
#Override
public int getItemCount() {
return feedData.size();
}
public class viewholder extends RecyclerView.ViewHolder implements View.OnClickListener {
Button btnMisFeeds;
FeedData dataHolder;
public viewholder(#NonNull View itemView) {
super(itemView);
btnMisFeeds = itemView.findViewById(R.id.btnMisFeeds);
btnMisFeeds.setOnClickListener(this);
}
public void setData(FeedData feedData) {
dataHolder = feedData;
btnMisFeeds.setText(dataHolder.getName());
}
#Override
public void onClick(View v) {
}
}
The code of my fragment:
public class FragmentInicio extends Fragment {
Button btnControlar, btnAddFeed;
View view;
String temperatura, distancia, infrarrojo, polvo;
// 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 static final String USER_PREFERENCES = "userPreferences";
private static final String TOKEN_KEY = "token";
private RequestQueue nQueue;
ArrayList<AdafruitFeed> adF;
AdafruitFeedAdapter adapterFeed;
RecyclerView recyclerView;
SharedPreferences userPreferences;
SharedPreferences.Editor userEditor;
String token;
public FragmentInicio() {
// 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 FragmentInicio.
*/
// TODO: Rename and change types and number of parameters
public static FragmentInicio newInstance(String param1, String param2) {
FragmentInicio fragment = new FragmentInicio();
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);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_inicio, container, false);
btnControlar = view.findViewById(R.id.btnControlar);
btnAddFeed = view.findViewById(R.id.btnAddFeed);
btnControlar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(v.getContext(), ControlActivity.class));
}
});
btnAddFeed.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(v.getContext(), AgregarFeedActivity.class));
}
});
nQueue = SingletonRequest.getInstance(view.getContext()).getRequestQueue();
adF = new ArrayList<>();
userPreferences = view.getContext().getSharedPreferences(USER_PREFERENCES, Context.MODE_PRIVATE);
userEditor = userPreferences.edit();
token = userPreferences.getString(TOKEN_KEY, null);
getFeeds();
return view;
}
public void getFeeds() {
String url = "https://cleanbotapi.live/api/v1/feeds";
final JsonObjectRequest getFeeds = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerFeed);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearManager = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(linearManager);
final Gson gson = new Gson();
final AdafruitFeed adafruitFeed = gson.fromJson(response.toString(), AdafruitFeed.class);
adapterFeed = new AdafruitFeedAdapter(adafruitFeed.getListFeedData());
temperatura = adafruitFeed.getListFeedData().get(0).getName();
distancia = adafruitFeed.getListFeedData().get(1).getName();
infrarrojo = adafruitFeed.getListFeedData().get(2).getName();
polvo = adafruitFeed.getListFeedData().get(3).getName();
recyclerView.setAdapter(adapterFeed);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("errorPeticion", error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "Bearer " + token);
return headers;
}
};
nQueue.add(getFeeds);
}
}
I trying to create an OnClickListener for everyone of my Adafruit feeds but i cant.
First of all the naming convention of a class should be in "PascalCase".
You need to define an interface that contains a method for your listener and pass it to the constructor of the adapter. And then also pass this listener to your ViewHolder by constructor.
Example:
public class AdafruitFeedAdapter extends RecyclerView.Adapter<AdafruitFeedAdapter.viewholder> {
public interface OnClickListener {
void onClick(FeedData data, int position);
}
ArrayList<FeedData> feedData;
OnClickListener clickListener;
public AdafruitFeedAdapter(ArrayList<FeedData> feedData,OnClickListener clickListener) {
this.feedData = feedData;
this.clickListener = clickListener;
}
...
#NonNull
#Override
public viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feed, parent, false);
return new viewholder(v,clickListener);
}
}
And in your viewholder modify it like below:
...
OnClickListener clickListener;
public viewholder(#NonNull View itemView,OnClickListener clickListener) {
super(itemView);
this.clickListener = clickListener;
btnMisFeeds = itemView.findViewById(R.id.btnMisFeeds);
btnMisFeeds.setOnClickListener(this);
}
...
#Override
public void onClick(View v) {
clickListener.onClick(dataHolder,getBindingAdapterPosition());
}
...
And your fragment:
public class FragmentInicio extends Fragment implements AdafruitFeedAdapter.OnClickListener {
...
#override
public void onClick(FeedData data, int position){
// TODO: implement your intent action
}
...
}
And your adapter: adapterFeed = new AdafruitFeedAdapter(adafruitFeed.getListFeedData(),FragmentInicio.this);
I've been trying to delete data from firebase with an OnClick RecyclerView method, but nothing works. I can't even make my OnClick method works. I have watched videos and tutorials, I've tried so much stuff and nothing helps...
Here is my adapter class:
public class myadapter extends RecyclerView.Adapter<myadapter.myviewholder>{
ArrayList<datamodel> dataholder;
public myadapter(ArrayList<datamodel> dataholder) {
this.dataholder = dataholder;
}
#NonNull
#Override
public myviewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
return new myviewholder(view);
}
#Override
public void onBindViewHolder(#NonNull myviewholder holder, int position) {
Glide.with(holder.itemView.getContext()).load(dataholder.get(position).getImageurl()).into(holder.CircleImg);
holder.header.setText(dataholder.get(position).getHeader());
holder.descr.setText(dataholder.get(position).getDescr());
holder.price.setText(dataholder.get(position).getPrec());
}
#Override
public int getItemCount() {
return dataholder.size();
}
class myviewholder extends RecyclerView.ViewHolder{
CircleImageView CircleImg;
TextView header, descr, price;
public myviewholder(#NonNull View itemView) {
super(itemView);
CircleImg = itemView.findViewById(R.id.circle1);
header = itemView.findViewById(R.id.txtheader1);
descr = itemView.findViewById(R.id.txtdescr1);
price = itemView.findViewById(R.id.txtprecio1);
}
}
And my fragment (the one that have the recyclerView):
public class articulos extends Fragment {
private FirebaseUser firebaseUser;
private String uid;
// 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 DatabaseReference myRef;
private Context mContext;
private myadapter myadapter;
RecyclerView recyclerView;
ArrayList<datamodel> dataholder;
public articulos() {
// 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 articulos.
*/
// TODO: Rename and change types and number of parameters
public static articulos newInstance(String param1, String param2) {
articulos fragment = new articulos();
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);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_articulos, container, false);
recyclerView = view.findViewById(R.id.rv);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
myRef = FirebaseDatabase.getInstance().getReference();
dataholder= new ArrayList<>();
getDataFromFirebase();
//datamodel ob1 = new datamodel("Esta nueva", "5000MXN", "wwsad.adasd", "asdasdsa");
// dataholder.add(ob1);
//recyclerView.setAdapter(new myadapter(dataholder));
return view;
}
private void getDataFromFirebase() {
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
uid = firebaseUser.getUid();
Query query = myRef.child("Usuarios").child(uid).child("articulos");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
ClearAll();
for(DataSnapshot snapshot1 : snapshot.getChildren()){
datamodel datamodel = new datamodel();
datamodel.setImageurl(snapshot1.child("imageurl").getValue(String.class));
datamodel.setDescr(snapshot1.child("descripcion").getValue(String.class));
datamodel.setHeader(snapshot1.child("nombre").getValue(String.class));
datamodel.setPrec(snapshot1.child("precio").getValue(String.class));
dataholder.add(datamodel);
}
myadapter = new myadapter(dataholder);
recyclerView.setAdapter(new myadapter(dataholder));
myadapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void ClearAll(){
if(dataholder != null){
dataholder.clear();
if(myadapter != null){
myadapter.notifyDataSetChanged();
}
}
dataholder = new ArrayList<>();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button mbtnNuevoArticulo = view.findViewById(R.id.btnNuevoArticulo);
mbtnNuevoArticulo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.agregarart);
}
});
}
If anyone can tell me what to do and how to do it, please.. I need it so bad
Try set onclicklistener on viewholder class
class myviewholder extends RecyclerView.ViewHolder implements View.OnClickListener {
CircleImageView CircleImg;
TextView header, descr, price;
public myviewholder(#NonNull View itemView) {
super(itemView);
CircleImg = itemView.findViewById(R.id.circle1);
header = itemView.findViewById(R.id.txtheader1);
descr = itemView.findViewById(R.id.txtdescr1);
price = itemView.findViewById(R.id.txtprecio1);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
//do something when clicked
}
}
You can apply onclick listener by using following code :
holder.header.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something.
}
});
add this code in your onBindViewHolder of Adapter. Just make sure to change the id of holder.
full code :
#Override
public void onBindViewHolder(#NonNull myviewholder holder, int position) {
Glide.with(holder.itemView.getContext()).load(dataholder.get(position).getImageurl()).into(holder.CircleImg);
holder.header.setText(dataholder.get(position).getHeader());
holder.descr.setText(dataholder.get(position).getDescr());
holder.price.setText(dataholder.get(position).getPrec());
holder.header.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something.
}
});
}
Create object of view inside your view holder and also initialize button.setOnClickListener(this) inside viewHolder itself and setting on click inside onBinfViewHolder(...)(only in JAVA). In kotlin you just need to set on click method inside onBindViewHolder(...).
Example:
class YourAdapter():RecyclerView.Adapter<YourAdapter.YourViewHolder>() {
class YourViewHolder(view: View):RecyclerView.ViewHolder(view){
val yourButton:Button = view.findViewById(R.id.landingViewBtn)
}
override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
holder.yourButton.setOnClickListener {
//do Something
val intent = Intent(context,nextActivity::class.java)
context.startActivity(intent)
}
}
}
since several days I try to handle data in recyclerview in viewpager2. The viewpager has an adapter managing the data in recyclerview. But everything I try to do seems to not work. Maybe I missundersteand the purpose or something. I hope you can help me.
This activity manages the viewpager and its adapter. It sends the data to the inner recyclerview:
public class AudioFilePanel extends AppCompatActivity
{
private String currentTab;
private ViewPagerAdapter adapter;
private ViewPager2 viewPager;
private TabLayout tabLayout;
private Map<String, List<String>> content;
private String path;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_file_panel);
viewPager = findViewById(R.id.view_pager2);
tabLayout = findViewById(R.id.tabs);
Button addFilesByTag = findViewById(R.id.add_files_with_tag);
if (null == currentTab)
{
currentTab = "music";
}
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()));
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setText(content.keySet().toArray()[position].toString())).attach();
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
#Override
public void onTabSelected(TabLayout.Tab tab)
{
currentTab = tab.getText().toString();
}
#Override
public void onTabUnselected(TabLayout.Tab tab)
{
}
#Override
public void onTabReselected(TabLayout.Tab tab)
{
}
});
addFilesByTag.setOnClickListener(l ->
{
Intent fileBrowser = new Intent(AudioFilePanel.this, FileBrowser.class);
startActivityForResult(fileBrowser, 1);
});
}
private void updateViweData()
{
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()));
viewPager.setAdapter(adapter);
}
private Map<String, List<String>> listByTag()
{
Map<String, List<String>> result = new HashMap<>();
DirectoryDao dao = new DirectoryDao(getApplicationContext());
String[] categories = {"music", "ambience", "effect"};
for (String category : categories)
{
List<String> directories =
dao.getDirectoriesForCategory(category).stream().map(Directory::getPath).collect(Collectors.toList());
result.put(category, directories);
}
return result;
}
This is the view pager adapter. It takes the data directly from the activity and should trigger data update in the inner recyclerview every time when an item will be clicked. See line 118-128:
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder>
{
private List<List<String>> filesListsByCategory;
private LayoutInflater mInflater;
private Context ctx;
private ItemListAdapter adapter;
private List<String> categoryFiles;
public ViewPagerAdapter(Context context, List<List<String>> data)
{
this.mInflater = LayoutInflater.from(context);
this.filesListsByCategory = data;
this.ctx = context;
}
#NotNull
#Override
public ViewHolder onCreateViewHolder(#NotNull ViewGroup parent, int viewType)
{
return new ViewHolder(mInflater.inflate(R.layout.item_viewpager, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
FileBrowserService fbs = new FileBrowserService();
categoryFiles = filesListsByCategory.get(position);
adapter = new ItemListAdapter(categoryFiles, new ItemList.OnListFragmentInteractionListener()
{
#Override
public void onListFragmentInteraction(String item)
{
categoryFiles = fbs.getFiles(categoryFiles.get(position));
categoryFiles.add(0, "previous directory");
updateUi(adapter, holder);
}
});
holder.myView.setAdapter(adapter);
}
private void updateUi(ItemListAdapter adapter, ViewHolder holder)
{
adapter.notifyDataSetChanged();
holder.myView.setAdapter(adapter);
}
#Override
public int getItemCount()
{
return filesListsByCategory.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
RecyclerView myView;
RelativeLayout relativeLayout;
ViewHolder(View itemView)
{
super(itemView);
myView = itemView.findViewById(R.id.my_list);
myView.setLayoutManager(new LinearLayoutManager(ctx));
relativeLayout = itemView.findViewById(R.id.container);
}
}
}
It is the adapter of inner recyclerview. It represents just a list of elements:
public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ViewHolder>
{
private List<String> files;
private final OnListFragmentInteractionListener mListener;
public ItemListAdapter(List<String> items, OnListFragmentInteractionListener listener)
{
files = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_item, parent, false));
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position)
{
holder.file = files.get(position);
holder.mContentView.setText(files.get(position));
holder.mView.setOnClickListener(v ->
{
if (null != mListener)
{
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.file);
}
});
}
#Override
public int getItemCount()
{
return files.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
private final View mView;
private final TextView mContentView;
private String file;
private ViewHolder(View view)
{
super(view);
mView = view;
mContentView = view.findViewById(R.id.content);
}
}
}
The last thing is the ItemList fragment.
public class ItemList extends Fragment
{
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
private OnListFragmentInteractionListener mListener;
/**
* Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon screen orientation
* changes).
*/
public ItemList()
{
}
// TODO: Customize parameter initialization
#SuppressWarnings("unused")
public static ItemList newInstance(int columnCount)
{
ItemList fragment = new ItemList();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener)
{
mListener = (OnListFragmentInteractionListener) context;
} else
{
throw new RuntimeException(context.toString() + " must implement OnListFragmentInteractionListener");
}
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (getArguments() != null)
{
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_item_list, container, false);
if (view instanceof RecyclerView)
{
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1)
{
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else
{
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new ItemListAdapter(getArguments().getStringArrayList("list"), mListener));
}
return view;
}
#Override
public void onDetach()
{
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this fragment to allow an interaction in this
* fragment to be communicated to the activity and potentially other fragments contained in that activity.
* <p/>
* See the Android Training lesson
* <a href= "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnListFragmentInteractionListener
{
// TODO: Update argument type and name
void onListFragmentInteraction(String item);
}
}
When I click, the data won't update. What I would like to have is:
This is what you have to do
add this method into your adapter class
public void updateData(List<String> filesList, int flag) {
if (flag == 0) { //append
for (int i = 0; i < filesList.size(); i++) {
files.add(messageList.get(i));
notifyItemInserted(getItemCount());
}
} else { //clear all
files.clear();
notifyDataSetChanged();
}
}
Then whenever you need to update recycle view call like below
mItemListAdapter.updateData(yourNewListOfItems, 0);
if you need to reset recycle-view call like below
mItemListAdapter.updateData(null, 1);
Add notifyDataSetChanged() in your adapter
This question already has answers here:
RecyclerView onClick
(49 answers)
Closed 4 years ago.
I'm using a Json to get data and images for my application. The images are displayed in a RecyclerView that is inside of a Fragment (Tab1.java) which is connected to MainActivity. I want to set it up in such a way, so that when the user clicks on an image in the RecyclerView, a new Activity (ViewImage.java) is launched and the image is displayed there.
So far, I've been able to fetch the Json data and display it in a recycler view. The images are displayed perfectly, but when I tried to setup "setItemOnClickListener", the application started to crash (I've marked that line with a comment in Tab1.java).
Tab1.java
/*
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Tab1.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Tab1#newInstance} factory method to
* create an instance of this fragment.
*/
public class Tab1 extends Fragment implements CardAdapter.OnItemClickListener{
// 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;
public static final String EXTRA_URL = "imageUrl";
private RecyclerView mRecyclerView;
private CardAdapter mCardAdapter;
private ArrayList<Card> mCardList;
TextView textView;
private OnFragmentInteractionListener mListener;
public Tab1() {
// 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 Tab1.
*/
// TODO: Rename and change types and number of parameters
public static Tab1 newInstance(String param1, String param2) {
Tab1 fragment = new Tab1();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
// #Override
public void onCreate(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tab1, container, false);
mRecyclerView = v.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mCardList = new ArrayList<>();
/*
* Retrofit code to fetch the Json data
*/
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService service = retrofit.create(ApiService.class);
Call<JsonResponse> call = service.getPopulationData();
final StringBuffer flagData = new StringBuffer();
call.enqueue(new Callback<JsonResponse>(){
#Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
ArrayList<Worldpopulation> population=new ArrayList(response.body()
.getWorldpopulation());
for (Worldpopulation j : population) {
String countryName = j.getCountry();
String imageUrl = j.getFlag();
int rank = j.getRank();
mCardList.add(new Card(imageUrl, countryName, rank));
}
mCardAdapter = new CardAdapter(getActivity(), mCardList);
mRecyclerView.setAdapter(mCardAdapter);
// This particular line of code is causing the application to crash.
// And I cannot figure out how this is supposed to be implemented.
mCardAdapter.setItemOnClickListener((CardAdapter.OnItemClickListener) getContext());
}
#Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
Log.d("JSONError", t.getMessage());
}
});
// Inflate the layout for this fragment
return v;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onItemClick(int position) {
Intent imagePreview = new Intent(getActivity(), ViewImage.class);
Card clickedItem = mCardList.get(position);
imagePreview.putExtra(EXTRA_URL, clickedItem.getImageUrl());
startActivity(imagePreview);
}
/*
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
CardAdapter.java
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.CardViewHolder> {
private Context mContext;
private ArrayList<Card> mCardList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setItemOnClickListener(OnItemClickListener listener) {
mListener = listener;
}
public CardAdapter(Context context, ArrayList<Card> cardList) {
mContext = context;
mCardList = cardList;
}
#Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.card, parent, false);
return new CardViewHolder(v);
}
#Override
public void onBindViewHolder(CardViewHolder holder, int position) {
Card currentItem = mCardList.get(position);
String imageUrl = currentItem.getImageUrl();
String countryName = currentItem.getCountryName();
int rank = currentItem.getRank();
holder.mTextViewCountry.setText(countryName);
holder.mTextViewRank.setText("Rank: " + rank);
Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
}
#Override
public int getItemCount() {
return mCardList.size();
}
public class CardViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextViewCountry;
public TextView mTextViewRank;
public CardViewHolder(View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image_view);
mTextViewCountry = itemView.findViewById(R.id.text_view_country_name);
mTextViewRank = itemView.findViewById(R.id.text_view_rank);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
});
}
}
}
ViewImage.java
public class viewimage extends appcompatactivity {
#override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_view_image);
// imageview where the image is to be displayed in this activity
imageview imageview = findviewbyid(r.id.fullscreenimage);
bundle bundle = getintent().getextras();
if (bundle != null) {
string imageurl = bundle.getstring("extra_url");
if (imageurl != null) {
picasso.get().load(imageurl).fit().centerinside().into(imageview);
}
}
}
}
as you already know this method is no longer available in the RecyclerView class.
My approach towards implementing onClick events in a RecyclerView is something like this:
class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
interface OnClickListener {
void onClick(Item item);
}
private final List<Item> dataset;
private final OnClickListener l;
public MyAdapter(List<Item> data, OnClickListener listener) {
this.dataset = data;
this.l = listener;
}
#Override MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = //inflate layout
MyClick click = new MyClick() {
onClick(int position) {
if (l != null) {
l.onClick(dataset.get(position));
}
}
};
return new MyViewHolder(click, v);
}
static class MyViewHolder {
final MyClick l;
public MyViewHolder(MyClick listener, View view) {
super(view);
l = listener;
// inflate views
view.setOnClickListener(new OnClickListener() {
if (l != null) {
l.onClick(getAdapterPosition());
}
});
}
interface MyClick {
void onClick(int position);
}
}
}
class MyActivity extends AppCompatActivity {
#Override void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set layout
MyAdapter adapter = new MyAdapter(getData(), new OnClickListener() {
#Override onClick(Item item) {
// do stuff with item
}
});
}
}
I'm a beginner on Android development and I was trying to make a simple app that has a recycleView inside a fragment using cardViews and when you click the like button inside of any of the items inside the list, the app then should send this item to another fragment called FavoriteFragment (which also contains recycleView) and display it here.
I tried to use an interface to do this, but whenever I click one of the like buttons, my activity does not receive the information (I tried to Log.d a message inside the method and is not being displayed)
here is the code for each of this:
My interface, what I am trying to use to pass the data from countries fragment-> adapter -> viewholder -> activity -> favorite fragment
public interface InterfaceListItemClickListener {
void listItemClickAction(ArrayList properties);
}
my CountriesFragment, which is the fragment that holds the first RecycleView:
public class CountriesFragment 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 OnFragmentInteractionListener mListener;
ArrayList<RecycleViewItem> listCountries = new ArrayList<>();
String names[] = {"Thailand", "Venezuela", "Sweden"};
int images[] = {R.drawable.thailand, R.drawable.venezuela, R.drawable.sweden};
RecyclerView myRecyclerView;
InterfaceListItemClickListener sender;
public CountriesFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sender = (InterfaceListItemClickListener) getActivity();
}
public static CountriesFragment newInstance(String param1, String param2) {
CountriesFragment fragment = new CountriesFragment();
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);
}
initializeList();
}
public void initializeList(){
listCountries.clear();
for(int i = 0; i < names.length; i++){
RecycleViewItem item = new RecycleViewItem();
item.setCardName(names[i]);
item.setImageResourceID(images[i]);
item.setIsFav(0);
item.setIsTurned(0);
listCountries.add(item);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_countries, container, false);
myRecyclerView = (RecyclerView) view.findViewById(R.id.recycleView);
myRecyclerView.setHasFixedSize(true);
LinearLayoutManager myLayoutManager = new LinearLayoutManager(getActivity());
myLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
ListsForFragments.populateCountriesList();
if (ListsForFragments.countriesList.size() > 0 & myRecyclerView != null) {
myRecyclerView.setAdapter(new MyAdapter(ListsForFragments.countriesList, sender));
}
myRecyclerView.setLayoutManager(myLayoutManager);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}
My Adapter class:
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{
private ArrayList<RecycleViewItem> list = new ArrayList<RecycleViewItem>();
InterfaceListItemClickListener sender = null;
public MyAdapter(ArrayList<RecycleViewItem> list, InterfaceListItemClickListener sender) {
this.list = list;
this.sender = sender;
}
public MyAdapter(ArrayList<RecycleViewItem> list) {
this.list = list;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_items, parent, false);
MyViewHolder holder = new MyViewHolder(view, sender);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.titleTextView.setText(list.get(position).getCardName());
holder.coverImageView.setImageResource(list.get(position).getImageResourceID());
holder.coverImageView.setTag(list.get(position).getImageResourceID());
}
#Override
public int getItemCount() {
return list.size();
}
}
My viewHolder class:
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView titleTextView;
public ImageView coverImageView;
public ImageView likeImageView;
public ImageView shareImageView;
public ImageView favoriteImageView;
public TextView favoriteTextView;
private ArrayList goesToFavourites = new ArrayList();
public MyViewHolder(View itemView, final InterfaceListItemClickListener sender) {
super(itemView);
titleTextView = (TextView) itemView.findViewById(R.id.titleTextView);
coverImageView = (ImageView) itemView.findViewById(R.id.coverImageView);
likeImageView = (ImageView) itemView.findViewById(R.id.likeImageView);
shareImageView = (ImageView) itemView.findViewById(R.id.shareImageView);
favoriteImageView = (ImageView) itemView.findViewById(R.id.imageView_favorite);
favoriteTextView = (TextView) itemView.findViewById(R.id.textView_name_favorite);
if (likeImageView != null) {
likeImageView.setTag(R.drawable.ic_like);
likeImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int id = (int) likeImageView.getTag();
if (id == R.drawable.ic_like) {
likeImageView.setTag(R.drawable.ic_liked);
likeImageView.setImageResource(R.drawable.ic_liked);
if(sender != null) {
getGoesToFavourites().add(coverImageView);
getGoesToFavourites().add(likeImageView);
sender.listItemClickAction(getGoesToFavourites());
}
} else {
likeImageView.setTag(R.drawable.ic_like);
likeImageView.setImageResource(R.drawable.ic_like);
}
}
});
}
}
public ArrayList getGoesToFavourites() {
return goesToFavourites;
}
public void setGoesToFavourites(ArrayList goesToFavourites) {
this.goesToFavourites = goesToFavourites;
}
}
My favoriteFragment class, the one receiving the information:
public class FavoriteFragment extends Fragment {
private OnFragmentInteractionListener mListener;
RecyclerView myRecyclerView;
ArrayList receiver = new ArrayList();
public FavoriteFragment() {
}
public void receiveData(ArrayList receiver){
this.receiver = receiver;
}
public static FavoriteFragment newInstance() {
FavoriteFragment fragment = new FavoriteFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_favorite, container, false);
myRecyclerView = (RecyclerView) view.findViewById(R.id.recycleView);
myRecyclerView.setHasFixedSize(true);
LinearLayoutManager myLayoutManager = new LinearLayoutManager(getActivity());
myLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
if (receiver != null & myRecyclerView != null) {
myRecyclerView.setAdapter(new MyAdapter(receiver));
}
myRecyclerView.setLayoutManager(myLayoutManager);
return view; }
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}
finally, my MainActivity, the bridge:
public class MainActivity extends AppCompatActivity implements
HostFragment.OnFragmentInteractionListener,
CountriesFragment.OnFragmentInteractionListener,
CitiesFragment.OnFragmentInteractionListener,
PlacesFragment.OnFragmentInteractionListener,
FavoriteFragment.OnFragmentInteractionListener,
ViewPagerFragment.OnFragmentInteractionListener,
InterfaceListItemClickListener{
FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fm = getSupportFragmentManager();
//if this is the first time we are running the app
if(savedInstanceState == null){
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.content, new ViewPagerFragment());
transaction.commit();
}
}
#Override
public void onFragmentInteraction(Uri uri) {
}
#Override
public void listItemClickAction(ArrayList list) {
FavoriteFragment favorite = (FavoriteFragment)
fm.findFragmentById(R.id.favorite);
favorite.receiveData(list);
Log.d("INTERFACE", "Data received!" + list);
}
}
If any extra information needed let me know and I'll provide.
EDIT: so trying to debug, I found out that the InterfaceListItemClickListener that MyViewHolder is a null, but not sure why...
EDIT 2: so I changed some things, inside My CountriesFragment:
I deleted the OnActivityCreated method and initialized the interface rather inside the onCreate like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initializeList();
sender = (InterfaceListItemClickListener) getActivity();
}
Now with this change, I was able to know that the findFragmentById inside my MainActivity is returning me a null. now, the way I am displaying this fragment is by using a ViewPager fragment which holds both fragments. this looks like this:
public class ViewPagerFragment extends Fragment {
private OnFragmentInteractionListener mListener;
public static ViewPager viewPager;
public ViewPagerFragment() {
// Required empty public constructor
}
public static ViewPagerFragment newInstance() {
ViewPagerFragment fragment = new ViewPagerFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(null);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_pager, container, false);
CustomAdapter adapter = new CustomAdapter(getChildFragmentManager()); //getChildFragmentManager
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPager.setAdapter(adapter);
return view;
}
public class CustomAdapter extends FragmentPagerAdapter {
public CustomAdapter(FragmentManager fm){
super(fm);
}
//position tells the program what fragment we are currently on/displaying
public Fragment getItem(int position){
switch (position){ //notice we don't use breaks on each case, due to the return statement on each.
case 0:return CountriesFragment.newInstance();
case 1: return FavoriteFragment.newInstance();
default: return FavoriteFragment.newInstance();
}
}
public int getCount(){
return 2;
}
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
How would I proceed in this case to finish passing the information?
OnCreateView() is called before OnActivityCreate() thats why your sender is null.Moreover,you must avoid setting or creating any objects in the OnCreateView(). Your fragment should be like this
public class CountriesFragment 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 OnFragmentInteractionListener mListener;
ArrayList<RecycleViewItem> listCountries = new ArrayList<>();
String names[] = {"Thailand", "Venezuela", "Sweden"};
int images[] = {R.drawable.thailand, R.drawable.venezuela, R.drawable.sweden};
RecyclerView myRecyclerView;
InterfaceListItemClickListener sender;
public CountriesFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sender = (InterfaceListItemClickListener) getActivity();
myRecyclerView.setHasFixedSize(true);
LinearLayoutManager myLayoutManager = new LinearLayoutManager(getActivity());
myLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
ListsForFragments.populateCountriesList();
if (ListsForFragments.countriesList.size() > 0 & myRecyclerView != null) {
myRecyclerView.setAdapter(new MyAdapter(ListsForFragments.countriesList, sender));
}
myRecyclerView.setLayoutManager(myLayoutManager);
}
public static CountriesFragment newInstance(String param1, String param2) {
CountriesFragment fragment = new CountriesFragment();
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);
}
initializeList();
}
public void initializeList(){
listCountries.clear();
for(int i = 0; i < names.length; i++){
RecycleViewItem item = new RecycleViewItem();
item.setCardName(names[i]);
item.setImageResourceID(images[i]);
item.setIsFav(0);
item.setIsTurned(0);
listCountries.add(item);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_countries, container, false);
myRecyclerView = (RecyclerView) view.findViewById(R.id.recycleView);
return view;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}