TabLayout
tab1 (Fragment1)
tab2 (Fragment2)
tab3 (Fragment3)
RecyclerView + CardView (OnClick)
On CardView ClickListner open another fragment in tab3. So how to open fragment in tab3.
Error is in getFragmentManager():
FragmentTransaction transaction = getFragmentManager().beginTransaction();
which gives
/Adapter/CardAdapter.java Error:cannot find symbol method getSupportFragmentManager()
Instead of this, I tried:
FragmentTransaction transaction = activity.getFragmentManager().beginTransaction();
FragmentTransaction transaction = itemview.getContext().getFragmentManager().beginTransaction();
But error is not resolve.
Here is my code:
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
List<NatureItem> mItems;
private int lastPosition = -1;
Context context;
TaskFragment main;
public CardAdapter(Context context,TaskFragment ma)
{
this.context=context;
main=ma;
}
public CardAdapter() {
super();
mItems = new ArrayList<NatureItem>();
NatureItem nature = new NatureItem();
nature.setName("The Paris Attack 2015");
nature.setDes("Lorem ipsum dolor sit amet.");
nature.setThumbnail(R.drawable.news1);
mItems.add(nature);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.custom_list, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
NatureItem nature = mItems.get(i);
viewHolder.tvNature.setText(nature.getName());
viewHolder.tvDesNature.setText(nature.getDes());
viewHolder.imgThumbnail.setImageResource(nature.getThumbnail());
// setAnimation(viewHolder.card,i);
}
#Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private int lastPosition = -1;
public ImageView imgThumbnail;
public TextView tvNature;
public TextView tvDesNature;
// Button btnclear,btncancle;
CardView card;
Activity activity;
Context co;
public ViewHolder(final View itemView) {
super(itemView);
imgThumbnail = (ImageView) itemView.findViewById(R.id.img_thumbnail);
tvNature = (TextView) itemView.findViewById(R.id.tv_nature);
tvDesNature = (TextView) itemView.findViewById(R.id.tv_des_nature);
card = (CardView) itemView.findViewById(R.id.card);
card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), "Clicked Card...", Toast.LENGTH_LONG).show();
ShareFragment newFragment = new ShareFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.viewFragments, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
}
}
}
Open new fragment as follows in your onclick
#Override
public void onClick(View view){
AppCompatActivity activity = (AppCompatActivity) view.getContext();
Fragment myFragment = new MyFragment();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, myFragment).addToBackStack(null).commit();
}
When you use adapter context then for access fragment manager you need to cast your context. So you should use this way.
YourParentActivity myActivity = (YourParentActivity)context
Now you can access method for fragment manager like ,
myActivity.getSupportFragmentManager();
But keep in your mind that your Fragment should be imported as a android.support.app.v4.Fragment otherwise there might be a casting problem.
If you open fragment for particular one tab then you should use getChildSupportFragmentManager() instead of getSupportFragmentManager()
Note : If you want to call fragment from adapter class then you should make interface and pass listener to your button click method and implement your activity with that interface.
Update :
Also you can pass FragmentManager to your adapter constructor. Like,
public FragmentManager f_manager;
public CardAdapter(Context context,TaskFragment ma , FragmentManager f_manager)
{
this.context = context;
this.f_manager = f_manager;
main=ma;
}
And after that you can use this.f_manager in your adapter class getView() method.
If you have used support library fragments or default fragments, be sure to use same of it every every where. And use "getSupportFragmentManager" or "getFragmentManager" carefully.
Pass context inside constructor.
public CardAdapter(Context context) {
super();
mItems = new ArrayList<NatureItem>();
NatureItem nature = new NatureItem();
nature.setName("The Paris Attack 2015");
nature.setDes("Lorem ipsum dolor sit amet.");
nature.setThumbnail(R.drawable.news1);
mItems.add(nature);
}
Inside onClick
....Your Code
ShareFragment newFragment = new ShareFragment();
FragmentTransaction transaction = /* Here is the change.*/context.getFragmentManager().beginTransaction();
transaction.replace(R.id.viewFragments, newFragment);
...Your Code
Update
Inside onClick call mainActivity setFragment method to replace fragment.
((MainActivity) context).setFragment(yourFragment);
public void setFragment(Fragment frag){
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.viewFragments, frag);
}
For moving from one fragment to another(from RecyclerView MyViewHolder class) use this
Fragment fragment = new AttendanceFragment();
FragmentManager fragmentManager = ((FragmentActivity) mContext).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
For the ones using Kotlin, assuming the fragment class you want to start is called MyFragment, and the container where you will put this fragment has id fragment_container_view. Probably you will do this inside the bind method inside your view holder.
itemView.setOnClickListener {
val activity = it.context as? AppCompatActivity
activity?.supportFragmentManager?.commit {
addToBackStack(MyFragment::class.toString())
setReorderingAllowed(true)
replace<MyFragment>(R.id.fragment_container_view)
}
}
Try this sniped :
ShareFragment newFragment = new ShareFragment();
MainActivity mainActivity = (MainActivity)itemView.getContext()
mainActivity.getFragmentManager().beginTransaction()
.replace(R.id.viewFragments, newFragment)
.addToBackStack(null)
.commit();
Related
I try to replace one fragment by another and get this error. I updated all libraries to latest version, but looks like I have mistake in the code while probably I don't understand something...
java.lang.IllegalStateException: FragmentManager has not been attached to a host.
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1727)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:321)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:286)
call from parent adapter feed:
private void clickId (View v, String idAuthor) {
new PrivateMessageShow();
}
class PrivateMessageShow
public class PrivateMessageShow extends FragmentActivity {
private FragmentTransaction fragmentTransaction;
private FragmentManager fragmentManager;
public PrivateMessageShow () {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.navigation_privateconversation, new PrivateMessageFragment(), "tag");
fragmentTransaction.addToBackStack("tag");
fragmentTransaction.commit();
}
}
Class PrivateMessageFragment which fails:
public class PrivateMessageFragment extends Fragment {
RecyclerView recyclerView;
public PrivateMessageFragment() {
}
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_private_message, container, false);
final Context mycontext = getActivity();
recyclerView = root.findViewById(R.id.recyclerViewPrivateMessage);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mycontext);
recyclerView.setLayoutManager(layoutManager);
return root;
}
}
You need to call fragment transaction code in Activity's onCreate method
Rename constructor, keep it as a method as below -
public void loadFragment () {
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.navigation_privateconversation, new
PrivateMessageFragment(), "tag");
fragmentTransaction.addToBackStack("tag");
fragmentTransaction.commit();
}
Call this method in onCreate of PrivateMessageShow acitivity.
Here I want to open fragment inside RecycleView but its show error but when I open activity its work here. When try to open a fragment with here of fragment manager the Recycler view class can not resolve to getFragmentManager() method inside it. Kindly provide a solution for it
public class AdapterMudra extends RecyclerView.Adapter<AdapterMudra.ReyclerViewHolder> {
private LayoutInflater layoutInflater;
private Context context;
private ArrayList<ItemMudra> items;
public AdapterMudra(Context context, ArrayList<ItemMudra> items) {
this.layoutInflater = LayoutInflater.from(context);
this.context = context;
this.items = items;
}
#Override
public ReyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = layoutInflater.inflate(R.layout.item_recycler_view, parent, false);
return new ReyclerViewHolder(item);
}
#Override
public void onBindViewHolder(final ReyclerViewHolder holder, int position) {
ItemMudra item = items.get(position);
holder.image.setImageResource(item.getDrawableMudra());
holder.appName.setText(item.getNameMudra());
}
#Override
public int getItemCount() {
return items.size();
}
class ReyclerViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private TextView appName;
private ReyclerViewHolder(final View v) {
super(v);
image = (ImageView) v.findViewById(R.id.image);
MyName = (TextView) v.findViewById(R.id.my_name);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(MyName.getText().toString()=="XYZ")
{
***//Fragment Not open here show error////
***
Here I want to call Fragment but its show error in GetFragment Manager***
Fragment fragment= new XYZ();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null); // this will manage backstack
transaction.commit();
}
if(MyName.getText().toString()=="ABC")
{
*** //Here Its Work When I open activity inside it***
Intent intent=new Intent(v.getContext(),ExtraActivityFormTesting.class);
context.startActivity(intent);
}
}
});
}
}
}
I assume your context is an Activity so you can do something like
((Activity) context).getFragmentManager()
First make sure the other fragmented class has the necessary implementations and constructors to be fragmented. Meaning, the class XYZ could be preventing your fragment transaction for missing out few essentials.
The following imports for instance
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
Now if thats in order. then Firstly I want you to reform
Fragment fragment= new XYZ();
to
XYZ fragment= new XYZ();
Second your fragment manager is badly constructed
reform this
Fragment fragment= new XYZ();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
to
XYZ fragment= new XYZ();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
*And for future references, you need to bring in the error log from the terminal
if your problem is using getFragmentManaget to implement do like below:
create
FragmentManager fm = getFragmentManager();
in your Fragment and passed it to your RecyclerView and again passed it to your ViewHolder and use it. so easy.
note: passed means send it as argumant to constructor
Fragment fragment= new FirstFragment();
FragmentManager manager = (MainActivityForRecy)context).getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null); // this will manage backstack
transaction.commit();
Toast.makeText(context, "you press clicked",Toast.LENGTH_SHORT).show();
I am converting ListView of my app to RecyclerView. On ListView, it was very easy to implement OnClickListener but in RecyclerView, we have to do it in adapter. I want to open a new Fragment when user clicks on a item. To do this I have to call FragmentManager in adapter which I am not able to do.
This is my code of RecyclerAdapter:
public ListItemViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//Call FragmentManager and add Fragment to it.
}
}
So, how to call FragmentManager and add Fragments in it. Is there any better way than this like sendingBroadcast or any other method.
You just need an activity context passed in your constructor. Be sure to call new Adapter(this,...) from activities and new Adapter(getActivity(),...) from fragments.
private Context context;
#Override
public void onClick(View v) {
FragmentManager manager = ((AppCompatActivity)context).getSupportFragmentManager();
}
To add on to the approved answer: if you still get an error you might need to replace this line;
FragmentManager manager = ((Activity)context).getFragmentManager();
With this
FragmentManager manager = ((AppCompatActivity)context).getSupportFragmentManager();
For me this was because I was using the support.v4.app.FragmentManager instead of the regular fragmentmanager
Still get an error?
As one comment below pointed out, this might throw a java.lang.ClassCastException: and log ... cannot be cast to android.support.v7.app.AppCompatActivity (check comments for details)
Their fix was to use this instead (I haven't tested it but it worked for them):
((AppCompatActivity)activity).getSupportFragmentManager()
Make sure to pass context to the ArrayAdapter or RecyclerViewAdpater,So that we can get it inside Adapter Class.
If your mainActivity is extending Activity then use :
FragmentManager fragmentManager = ((Activity)context).getFragmentManager();
If your mainActivity is extending AppCompatActivity then use :
FragmentManager fragmentManager = ((AppCompatActivity)context).getSupportFragmentManager();
Best option would probably be to have the Fragment that instantiates the RecyclerAdapter to implement and interface like this:
public class MyRecyclerAdapter extends Adapter<RecyclerAdapter.ViewHolder> {
private ItemType[] mItems;
private MRAItemClickedListener mListener;
public MyRecyclerAdapter(Context ctx, MRAItemClickedListener listener){
mListener = listener;
...
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
mListener.onItemClicked(mItems[position]);
}
});
}
interface MRAItemClickedListener {
void onItemClicked(ItemType item);
}
}
public class MyFragment ... implements MRAItemClickedListener {
public void onItemClicked(ItemType item){
// do stuff with item
}
}
in kotlin you can use this code:
val fm : FragmentManager= (context as AppCompatActivity).supportFragmentManager
You just need an activity context passed in your constructor. Be sure to call new Adapter(this,...) from activities and new Adapter(getActivity(),...) from fragments.
private Context context;
#Override
public void onClick(View v) {
FragmentManager manager = ((Activity) context).getFragmentManager();}
I know this is too late for you but to anyone else who might see this.
So instead of doing m vai did you can pass the context of the fragment when you first initialize your adapter.
So in your constructor for your adapter you can add an argument like this
// variable to hold fragment
private Fragment fragment;
public MyCustomAdapter(Fragment fragment)
{
this.fragment = fragment;
}
and in your fragment you can just initialize if like this
MyCustomAdapter myAdapter = new MyCustomAdapter(this);
finally you can call
Fragment fragment = new myNewFragment();
FragmentManager fragmentManager = context.getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment)
.commit();
so you can start a new fragment
Instantiate the fragmentManager in the activity itself.
MyActivity.java
FragmentManager fragmentManager = getFragmentManager();
adapter = new CustomAdapter(productsList, fragmentManager);
CustomAdapter.java
CustomAdapter implements MyClickListner{
CustomAdapter(Arraylist<MyProduct>productsList, FragmentManager fragmentManager) {
this.productList = productsList;
this.fragmentManager = fragmentManager;
}
#override
clickFunction(){
Fragment myFragment= new MyFilterFragment();
((MyFilterFragment) myFragment).show(this.fragmentManager,"tag");
}
MyClickListener.java
public interface MyClickListener(){
public clickFunction();
}
You could pass FragmentManager reference while creating viewholder so your class for Viewholder could be as follows
class ListItemViewHolder {
FragmentManager manager;
public ListItemViewHolder(View itemView,FragmentManager manager) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
itemView.setOnClickListener(this);
this.manager = manager;
}
#Override
public void onClick(View v) {
//Call FragmentManager and add Fragment to it.
manager.beginTransaction...
}
}
Here, My class is like this
public class TicketAdapter extends ArrayAdapter<Ticket> {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
TicketHolder holder = null;
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new TicketHolder();
holder.ticket = items.get(position);
holder.removeTicketButton = (ImageButton)row.findViewById(R.id.ticket_remove);
holder.removeTicketButton.setTag(holder.ticket);
holder.settingTicketButton=(ImageButton)row.findViewById(R.id.ticket_setting);
holder.settingTicketButton.setTag(holder.ticket);
holder.settingTicketButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
holder.name = (TextView)row.findViewById(R.id.ticket_name);
setNameTextChangeListener(holder);
// holder.value = (TextView)row.findViewById(R.id.atomPay_value);
// setValueTextListeners(holder);
row.setTag(holder);
setupItem(holder);
return row;
}
}
And my another java file is like this
public class FreeFragment extends Fragment
{
}
Here, I want to call FreeFragment class from TicketAdapter class. While clicking on (R.id.settingTicketButton) this button, FreeFragment need to be called. How to call this Fragment from DataAdapter? Is it possible? Please Help.
The best method would be passing the FreeFragment instance an a variable in the constructor of the TicketAdapterand store it inside the adapter.
If this is not feasible you can use the following approch.
Fragment fragment = ((Activity)context).getfragmentmanager.findfragmentById(R.id.your_fragment_container_id);
Add this code in the contructor
I wouldn't access FreeFragment directly from TicketAdapter because you don't know if the fragment is added and visible. I would define a method in owner activity that would be called from adapter. In this method check first if the fragment is not-null and then call whatever method from fragment. Something like (in parent Activity):
public void callFragmentMethod() {
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentByTag("SOME_TAG");
if(fragment != null) {
FreeFragment ff = (FreeFragment) fragment;
ff.callSomeMethod();
}
}
Pass the reference of the activity to the adapter and call above method from adapter. Or, to make the code more beautiful and easier to maintain and extend, define and interface with above method, have the activity extending the interface and send the interface as reference to adapter.
easy step to handle this condition
1)create one Interface give any name
2) define method inside as per ewquirement example MyCommumicator
example i want to refreshData so i define method inside my interface like
public void refreshData();
now take reference of interface in adater like
MyCommumicator myCommumicator;
3)implement that interface into your Fragment and implement method.
4)create Constractor of Adapter like
public TicketAdapter(other params...,MyCommumicator MyCommumicator){
this.myCommumicator = myCommumicator;
}
6) Time of calling just call like this
myCommumicator.refreshData();
now enjoy
ANOTHER WAY
Use LocalBroadCast.
so if your adapter have access to FragmentActivity, you must call FragmentManager and further call fragment
FragmentManager fragmentManager = yourFragmentActivity.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Create new fragment and transaction
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, yourFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
I found my solution. I have written the following code in TicketAdapter.java file..
holder.settingTicketButton=(ImageButton)row.findViewById(R.id.ticket_setting);
holder.settingTicketButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Fragment freeFragment = new FreeFragment();
if (freeFragment != null)
switchFragment(freeFragment);
Log.e("adapter_click_setting","adapter_click_setting");
}
});
}
private void switchFragment(Fragment newFragment)
{
if (context == null)
{
Log.e("null_context","nulllll");
return;
}
if (context instanceof AddNewTicket) {
Log.e("meth_calling","method_calling");
AddNewTicket feeds = (AddNewTicket) context;
feeds.switchContent(newFragment);
}
}
And I have written the following method in AddNewTicket.java file..
public void switchContent(android.support.v4.app.Fragment newFragment) {
// TODO Auto-generated method stub
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, newFragment).commit();
}
Here, the R.id.fragment_container is the id of my ticket_listview.xml file. I have declared FragmentLayout in my that Xml file....
I have an activity with two fragments in it (both dynamically created), one of which is a ListFragment. I have implemented an onListItemClick handler in the activity. When an item is clicked, I want to replace both fragments with other fragments, and populate a TextView. However, after replacing the fragments I can't seem to get the View object I need to manipulate the TextView in the new Details fragment -- it returns null. Here is some relevant code (onListItemSelected is the handler that processes onListItemClick in the main activity).
#Override
public void onListItemSelected(int index) {
inflateCheckinFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
cif = new checkInFragment();
fragmentTransaction.replace(R.id.action_container, cif, "ACTIONS");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit()
FragmentTransaction fragmentTransaction2 = fm.beginTransaction();
gdf = new GeolocDetailsFragment();
fragmentTransaction2.replace(R.id.fragment_container, gdf, "DETAILS");
fragmentTransaction2.addToBackStack(null);
fragmentTransaction2.commit();
View gdfView = gdf.getView();
TextView tv = (TextView) gdfView.findViewById(R.id.textPOI);
tv.setText(printPOI(poiList.get(index)));
}
I ended up just setting up the data in the onListItemSelected method. selectedPOI is a private class member.
public void onListItemSelected(int index) {
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.action_container, cif, TAG_CHECKIN);
fragmentTransaction.replace(R.id.fragment_container, gdf, TAG_DETAILS);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
selectedPOI = poiList.get(index);
}
Then in the GeolocDetailsFragment class, I set up a handler to be called in the Activity in the Fragment's onCreateView method to set the TextView value.
public class GeolocDetailsFragment extends Fragment {
private TextSetter textSetter;
public interface TextSetter {
public String getActivityText();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.geoloc_details_fragment, container, false);
TextView detailsText = (TextView) view.findViewById(R.id.textPOI);
detailsText.setText(textSetter.getActivityText());
return view;
}
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
textSetter = (TextSetter) activity;
}
catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnGetPOIListener");
}
}
}
Finally, I implemented getActivityText() in the main activity to get the string to pass to the TextView.
#Override
public String getActivityText() {
return printPOI(selectedPOI);
}
You should make use of the Fragments in a fashion like this, making the TextView public in your fragment helps the Activity to access it directly, and there fore change the value.
Class GeolocDetailsFragment extends Fragments{
public TextView tv;
onCreateView(){
tv= (TextView) rootView.findViewById(R.id.textPOI);
}
}
//IN YOUR ACTIVITY
#Override
public void onListItemSelected(int index) {
gdf = new GeolocDetailsFragment();
gdf.tv.setText(printPOI(poiList.get(index)));
}