I have a list using the RecyclerView, what I want is that when I click on the list item, it opens a fragment, I've been searching and I only found it with an activity, but I'm working only with fragments, if I use activity it disappears with my action bar, it's all set in the fragment.
This is my adapter class:
public class CreditCardAdapter extends RecyclerView.Adapter<CreditCardHolder> {
private final List<CreditCard> creditList;
public CreditCardAdapter(List<CreditCard> creditList) {
this.creditList = creditList;
}
#NonNull
#Override
public CreditCardHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.credit_card_item, parent, false);
return new CreditCardHolder(view);
}
#Override
public void onBindViewHolder(#NonNull CreditCardHolder holder, int position) {
CreditCard credit = creditList.get(position);
String flag = credit.getFlag();
holder.flag.setText(flag);
String owner = credit.getOwner();
holder.owner.setText(owner);
String valueLimit = String.format("%.2f", credit.getLimit());
holder.limit.setText(valueLimit.replace(".", ","));
holder.creditCardId = credit.getId();
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Method on click
}
});
}
#Override
public int getItemCount() {
return creditList.size();
}
}
I need to send the credit card id to the fragment, to call the controller and get the information from the database, I tried it with the intent, but it only worked if I call the activity with startActivity(intent).
So here it is the fragment class:
public class InfoCreditCardFragment extends Fragment {
public InfoCreditCardFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_info_credit_card, container, false);
String id; //Here I need the id from the Adapter
TextView flagInfoTxt = view.findViewById(R.id.flagInfoTxt);
TextView ownerInfoTxt = view.findViewById(R.id.ownerInfoTxt);
CreditCard cc = CreditCardController.getWithId(id);
flagInfoTxt.setText(cc.getFlag());
ownerInfoTxt.setText(cc.getOwner());
return view;
}
}
If anyone knows anything to help, please, I'm desperate.
So, I managed to go to the fragment using this:
Bundle bundle = new Bundle();
bundle.putString("id", holder.creditCardId);
InfoCreditCardFragment fragment = new InfoCreditCardFragment();
AppCompatActivity activity = (AppCompatActivity) view.getContext();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, fragment).addToBackStack(null).commit();
And inside the fragment I just get the bundle with "getArguments().getString("id");"
Related
Problem Statement
I have a problem of data being changed in fragment whenever the data is modified in the BottomSheetDialogFragment
App Description
In my app I have the MainActivity which host 2 Fragment in it's ViewPager. 1st Fragment for app content and 2nd Fragment (let's call it GalleryFragment) that shows the gallery view. User can tap on gallery item which loads up the BottomSheet (let's call it GalleryBottomSheet) - that hosts RecyclerView to show gallery item in full screen. Now initially app feeds the GalleryFragment with the ArrayList to show the gallery items. When user clicks on the Gallery item, this ArrayList is passed to the GalleryBottomSheet.
So What's Happening
What's happening is whenever I am removing an item from the ArrayList in my GalleryBottomSheet, It automatically also remove that item in the ArrayList of GalleryFragment. In short, Any update in the Arraylist from GalleryBottomSheet impacting the ArrayList in GalleryFragment
What do you want
I want seperation of concerns. I don't want the change made in the ArrayList of GalleryBottomSheet to impact the original ArrayList of GalleryFragment
Show me the damn code
To make this question concise, I am adding only the important part of the code.
~ GalleryFragment.java
public class GalleryFragment extends Fragment {
private RecyclerView recyclerView;
private ArrayList<String> arrayList = new ArrayList<>(); //This is the one which will be passed to the GalleryBottomSheet
private GalleryAdapter galleryAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_gallery, container, false);
//setting up all the UI work...
arrayList = FindFiles(); //FindFiles is a private function searching for all file in the dir and adding the path as a string to the arraylist
galleryAdapter = new GalleryAdapter(getActivity()); //init the adapter
recyclerView.setAdapter(galleryAdapter); //setting the adapter
return view;
}
}
private class GalleryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Activity activity;
GalleryAdapter(Activity context) {
this.activity = context;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_content_item, parent, false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if(holder instanceof ItemViewHolder){
//setting up stuff..
}
}
#Override
public int getItemCount() {
return arrayList.size();
}
private class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView imageView;
ItemViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putStringArrayList("list", arrayList);
GalleryBottomSheet galleryBottomSheet= GalleryBottomSheet.newInstance();
galleryBottomSheet.setOnRefreshListener( new GalleryBottomSheet.GalleryInterface() {
#Override
public void onRefresh() {
//here the actual arrayList size reduced even though the arrayList that was modified exist in GalleryBottomSheet
System.out.println("CURRENT LIST SIZE: " + arrayList.size());
}
});
galleryBottomSheet.setArguments(bundle);
galleryBottomSheet.show(getParentFragmentManager(), "galleryPager");
}
}
~ GalleryBottomSheet.java
public class GalleryBottomSheet extends BottomSheetDialogFragment {
static GalleryBottomSheet newInstance() {
return new GalleryBottomSheet();
}
public interface GalleryInterface {
void onRefresh();
}
private RecyclerView recyclerView;
private ViewAdapter viewAdapter;
private Button deleteBtn;
private GalleryInterface galleryInterface;
public void setOnRefreshListener( GalleryInterface galleryInterface){
this.galleryInterface = galleryInterface;
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//.. setting up sheetDialog
return bottomSheetDialog;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(BottomSheetDialogFragment.STYLE_NO_FRAME, R.style.GalleryBottomStyle);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.gallery_sheet, container, false);
Bundle bundle = getArguments();
ArrayList<String> filePathArr = bundle.getStringArrayList("list"); //here arrayList from GalleryFragment
//Setting up all UI views...
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int positionPager = recyclerView.computeVerticalScrollOffset(); //just for demo, in the actual app we are using addOnScrollListener for position
filePathArr.remove(positionPager);
viewAdapter.notifyItemRemoved(positionPager);
galleryInterface.onRefresh(); //this is where GalleryFragment shows that the arraylist is modified too.
Toast.makeText(getActivity(), "Deleted Successfully",Toast.LENGTH_SHORT).show();
}
});
return view;
}
//setting up viewAdapter and other stuff
}
Well, it turns out the main problem is that object is stored in memory by reference. By modifying the arrayList from GalleryBottomSheet it also changes the original arrayList since the exact arrayList was referred in GalleryBottomSheet from GalleryFragment. The solution is to simply initializing a new ArrayList in GalleryBottomSheet
Changing from:
ArrayList<String> filePathArr = bundle.getStringArrayList("list");
to:
ArrayList<String> filePathArr = new ArrayList<>(bundle.getStringArrayList("list"));
I am using navigation component in my app I have 2 fragments one fragments list of items and another shows detail of an item when user clicks on an item in fragments 1 it goes to detail fragment and when I switch back to first fragment then all the listing duplicates again.
Below is my code:
CakeFragment.java
public class CakeFragment extends Fragment {
List<AllCakes> allCakeList = new ArrayList<>();
AllCakesAdapter adapter;
BottomNavigationView navView;
FragmentCakeBinding fragmentCakeBinding;
public CakeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeBinding = FragmentCakeBinding.inflate(inflater,container,false);
navView = getActivity().findViewById(R.id.navView);
navView.setVisibility(View.GONE);
getAllCakes();
return fragmentCakeBinding.getRoot();
}
private void getAllCakes(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<AllCakes>> call = apiService.getAllCake();
call.enqueue(new Callback<List<AllCakes>>() {
#Override
public void onResponse(Call<List<AllCakes>> call, Response<List<AllCakes>> response) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
fragmentCakeBinding.allCakeRecycler.setHasFixedSize(true);
fragmentCakeBinding.allCakeRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
#Override
public void onFailure(Call<List<AllCakes>> call, Throwable t) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
TastyToast.makeText(getActivity(),t.getMessage(),TastyToast.LENGTH_SHORT,TastyToast.ERROR).show();
}
});
}
}
AllCakesAdapter.java
public class AllCakesAdapter extends RecyclerView.Adapter<AllCakesAdapter.ViewHolder> {
Context context;
List<AllCakes> allCakeList;
public AllCakesAdapter(Context context, List<AllCakes> allCakeList) {
this.context = context;
this.allCakeList = allCakeList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.allcakes_row,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
AllCakes model = allCakeList.get(position);
Glide.with(context).load(model.getImgurl()).into(holder.allCakeImg);
holder.allCakeName.setText(model.getName());
holder.cakeDisPrice.setPaintFlags(holder.cakeDisPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.moreCake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavController navController = Navigation.findNavController((Activity) context,R.id.fragment);
navController.navigate(R.id.cakeDetailFragment);
}
});
}
#Override
public int getItemCount() {
return allCakeList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView allCakeImg;
Button moreCake;
TextView allCakeName;
public ViewHolder(#NonNull View itemView) {
super(itemView);
allCakeImg = itemView.findViewById(R.id.allCakeImg);
moreCake = itemView.findViewById(R.id.moreCake);
allCakeName = itemView.findViewById(R.id.allCakeName);
}
}
}
CakeDetailFragment.java
public class CakeDetailFragment extends Fragment {
FragmentCakeDetailBinding fragmentCakeDetailBinding;
public CakeDetailFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeDetailBinding = FragmentCakeDetailBinding.inflate(inflater,container,false);
return fragmentCakeDetailBinding.getRoot();
}
}
Why is this happening?
private void getAllCakes(){
...
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
...
you're calling:
allCakeList.addAll(response.body());
every time without clearing your list out.
you have to clear that list:
allCakeList.clear();
allCakeList.addAll(response.body());
this is something you can easily determine yourself by just putting a breakpoint on your allCakeList to see what's inside it, if you haven't ever done this before, you should consider trying it out
Try the following and see if it solves your issue
CakeFragment.java
allCakeList.clear();
allCakeList.addAll(response.body());
//rest of the logic remains same
The RecyclerView has components with text, I need that by clicking on a component that has text for example "Chess", the DialogFragment opens and the text "Chess" from the RecyclerView component is transferred to the TextView which is inside this DialogFragment.
To get a key from my item layout file, I write this:
Bundle bundle = new Bundle();
bundle.putString("item", String.valueOf(dialogSRS));
dialogSRS.setArguments(bundle);
But what needs to be written in the DialogFragment so that our text is transferred there?
I am writing the following in my DialogFragment but it doesn't work
public class DialogSkatingRinkSchedule extends DialogFragment{
TextView number_srs_2;
TextView start_srs_2;
TextView end_srs_2;
TextView cost_srs_2_1;
TextView cost_srs_2_2;
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_skatingrinkschedule, container, false);
number_srs_2 = view.findViewById(R.id.number_srs_2);
start_srs_2 = view.findViewById(R.id.start_srs_2);
end_srs_2 = view.findViewById(R.id.end_srs_2);
cost_srs_2_1 = view.findViewById(R.id.cost_srs_2_1);
cost_srs_2_2 = view.findViewById(R.id.cost_srs_2_2);
Bundle getArguments = new Bundle();
number_srs_2 = (TextView) getArguments.getSerializable("item");
return view;
}
}
My adapter
public class AdapterSkatingRinkSchedule extends RecyclerView.Adapter<AdapterSkatingRinkSchedule.SkatingRinkScheduleViewHolder> {
public ArrayList<ItemSkatingRinkSchedule> mSkatingRinkScheduleList;
public List<ItemSkatingRinkSchedule> mSearch;
private AppCompatActivity mActivity;
public AdapterSkatingRinkSchedule(ArrayList<ItemSkatingRinkSchedule> SkatingRinkScheduleList) {
mSkatingRinkScheduleList = SkatingRinkScheduleList;
mSearch = new ArrayList(mSkatingRinkScheduleList);
}
#NonNull
#Override
public SkatingRinkScheduleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_srs, parent, false);
return new SkatingRinkScheduleViewHolder(v);
}
public static class SkatingRinkScheduleViewHolder extends RecyclerView.ViewHolder {
public TextView number_srs, start_time_srs, end_time_srs, cost_1_srs, cost_2_srs;
public TextView number_srs_2;
public LinearLayout ll_main;
public SkatingRinkScheduleViewHolder(View itemView) {
super(itemView);
number_srs = itemView.findViewById(R.id.number_srs);
start_time_srs = itemView.findViewById(R.id.start_time_srs);
end_time_srs = itemView.findViewById(R.id.end_time_srs);
cost_1_srs = itemView.findViewById(R.id.cost_1_srs);
cost_2_srs = itemView.findViewById(R.id.cost_2_srs);
ll_main = itemView.findViewById(R.id.ll_main);
}
}
#SuppressLint("LongLogTag")
#Override
public void onBindViewHolder(SkatingRinkScheduleViewHolder holder, int position) {
ItemSkatingRinkSchedule currentItem = mSkatingRinkScheduleList.get(position);
holder.number_srs.setText(currentItem.get_session_number());
holder.start_time_srs.setText(currentItem.get_session_start());
holder.end_time_srs.setText(currentItem.get_session_end());
holder.cost_1_srs.setText(currentItem.get_weekdays());
holder.cost_2_srs.setText(currentItem.get_weekends_and_holidays());
holder.ll_main.setOnClickListener(v -> {
DialogSkatingRinkSchedule dialogSRS = new DialogSkatingRinkSchedule();
dialogSRS.show(((AppCompatActivity) v.getContext()).getSupportFragmentManager(), "item");
Bundle bundle = new Bundle();
bundle.putString("item", String.valueOf(dialogSRS));
dialogSRS.setArguments(bundle);
});
holder.getAdapterPosition();
}
#Override
public int getItemCount() {
return mSkatingRinkScheduleList.size();
}
}
You can access the arguments Bundle of a Fragment or DialogFragment by calling the method getArguments(). Since you put a String there previously by writing
bundle.putString("item", String.valueOf(dialogSRS));
you should retrieve the value by using getString("item"). Then you can display the text from the Bundle with the TextView as follows:
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_skatingrinkschedule, container, false);
number_srs_2 = view.findViewById(R.id.number_srs_2);
// assign other Views like before
Bundle args = getArguments();
String myText = args.getString("item");
number_srs_2.setText(myText);
return view;
}
I'm setting up an image adapter in my fragments. I recently learn the usefulness of Fragments and Therefore I am trying to switch from the traditional activities to a central activity with multiple fragments. But I cant get to display my images' infinite cycler view.
I have tried reading answers from previous questions here on Stack overflow (ImageAdapter cannot be applied to fragment class and ImageAdapter cannot be applied to a Fragment Class) but I didnt really understand anything perhaps because I am a beginner in android studio with no educational background in coding. I have also tried youtube and everywhere.
I havent found tutorials to do this, I understand that fragments is relatively new in android studio
This is the fragment I am trying to switch to
public TrendingFragment() {
// Required empty public constructor
}
private static final String TAG = "Trending";
HorizontalInfiniteCycleViewPager viewPager;
List<TrendingHolder> TrendingList = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragme
View view = inflater.inflate(R.layout.fragment_trending, container, false);
initData();
viewPager = view.findViewById(R.id.view_pager);
viewPager.setAdapter(new TrendingAdapter(getActivity()));
return view;
}
private void initData() {
//Adding the Images on board
TrendingList.add(new TrendingHolder(R.drawable.ad_test));
TrendingList.add(new TrendingHolder(R.drawable.burger_test));
TrendingList.add(new TrendingHolder(R.drawable.italian_test));
TrendingList.add(new TrendingHolder(R.drawable.pizza_test));
}
}
This is my adapter class
public class TrendingAdapter extends PagerAdapter {
Context context;
List<TrendingHolder> TrendingList;
private static final String TAG = "TrendingAdapter";
public TrendingAdapter(Context context, List<TrendingHolder> trendingList) {
this.context = context;
this.TrendingList = trendingList;
}
#Override
public int getCount() {
return TrendingList.size();
}
#Override
public boolean isViewFromObject(View view, #NonNull Object o){
return view.equals(o);
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((View)object);
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
//Inflate View
View view = LayoutInflater.from(context).inflate(R.layout.card_item, container, false);
//View
ImageView trending_image = (ImageView)view.findViewById(R.id.trending_holder);
//Set Data
trending_image.setImageResource(TrendingList.get(position).getImage());
//set On Event Click
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//shop activity comes here
Log.d(TAG, "onClick: added to Cart");
}
});
container.addView(view);
return view;
}
}
This is my model for the images
public class TrendingHolder {
private int image;
public TrendingHolder(){
}
public TrendingHolder(int image) {
this.image = image;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
}
I am getting this error TrendingAdapter( )
in TrendingAdapter cannot be applied
to
(androidx.fragment.app.FragmentActivity) in my Trending Fragment
It seems like missing constructor parameter. The constructor of TrendingAdapter accepts 2 parameters public TrendingAdapter(Context context, List<TrendingHolder> trendingList). But you pass 1 parameter viewPager.setAdapter(new TrendingAdapter(getActivity()));.
I created a ListView within a fragment and populated it with data from a class called Workout within the onStart() method. I set an Adapter and the list shows up fine. I would like to now be able to get the value of the specific row that the user clicks but am unable to implement an onItemClicked() method. Does anyone know how I can get this value? Thank you.
public class WorkoutListFragment extends Fragment {
static interface WorkoutListListener{
void itemClicked(long id);
}
private WorkoutListListener listener;
private ListView workoutList;
private LayoutInflater inflate;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflate = inflater;
return inflater.inflate(R.layout.fragment_workout_list, container, false);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (WorkoutListListener)activity;
}
#Override//ISSUE IS IN HERE
public void onStart() {
super.onStart();
View view = getView();
String[]names = new String[Workout.workouts.length];
for (int i = 0; i < names.length; i++){
names[i] = Workout.workouts[i].getName();
}
if (view!=null){
workoutList = (ListView)view.findViewById(R.id.listView);
ArrayAdapter<String>adapter = new ArrayAdapter<String>(inflate.getContext(),
android.R.layout.simple_list_item_1,names);
workoutList.setAdapter(adapter);
}
//HOW CAN I NOW GET THE VALUE OF THE ITEM CLICKED?
// I TRIED THIS BUT IT'S NOT RECOGNIZED
workoutList.setOnClickListener(new onItemClickListener);
}
Use this:
workoutList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// the 'position' argument is the position you are looking for
}
});
EDIT:
I noticed that you are not initializing the workoutList listView. You should do that in the OnCreateView method:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_workout_list, container, false);
workoutList = (ListView) view.findViewById(R.id.workoutListView); // assuming that your listView's id is "#+id/workoutListView"
return view;
}