How can I call a method from nested fragment - android

I have a fragment(this is one tab of my tabhost) "fragA" inside other fragment "fragB" but I need to call one method of "fragB" from "fragA".
when I do from an activity, I do this:
FragB detailsFragment=(FragB)getSupportFragmentManager().findFragmentById(R.id.detailFragment);
detailsFragment.consultaWS(convertIntWebService(categoria),"Pdf");
please, help me

I could finally solve it this way, in fragA:
FragB parentFragment = (FragB) getChildFragmentManager()
.findFragmentByTag("detallesFragBusqueda");
if (parentFragment != null) {
parentFragment.consultaWS("", "AllPdf");
}

Your activity should facilitate all communication between fragments. Just create a method in your Activity that a fragment can call, which will tell another fragment to do something.

If FragA is inside FragB, you can do the same from within your FragA.
FragB parentFragment = (FragB)getActivity().getSupportFragmentManager().findFragmentById(R.id.detailFragment);
parentFragment.fragmentBMethod();

Read this http://developer.android.com/training/basics/fragments/communicating.html.
This document explains that how can you communicate between Activity and Fragment
and also between 2 Fragments

Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_main_container);
if (fragment != null) {
((TabLayoutFragment)fragment).tabClickDisable();
}

Related

Open a fragment from a recyclerview (which is a fragment) [duplicate]

My application has a Fragment inside its Activity. I would like to programmatically replace the fragment by another one from the current fragment itself.
For example, if I click on a button inside the fragment, the fragment should be replaced with another one, but the activity should remain the same.
Is it possible? If so, how to do it?
It's actually easy to call the activity to replace the fragment.
You need to cast getActivity():
((MyActivity) getActivity())
Then you can call methods from MyActivity, for example:
((MyActivity) getActivity()).replaceFragments(Object... params);
Of course, this assumes you have a replaceFragments() method in your activity that handles the fragment replace process.
Edit: #ismailarilik added the possible code of replaceFragments in this code with the first comment below which was written by #silva96:
The code of replaceFragments could be:
public void replaceFragments(Class fragmentClass) {
Fragment fragment = null;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment)
.commit();
}
from the official docs:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
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, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
In this example, newFragment replaces whatever fragment (if any) is currently in the layout container identified by the R.id.fragment_container ID. By calling addToBackStack(), the replaced fragment is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.
The behavior you have described is exactly what fragments are designed to do. Please go through the official guide for a thorough understanding of fragments which will clear up all your questions.
http://developer.android.com/guide/components/fragments.html
Please note that fragment should NOT directly replace itself or any other fragments. Fragments should be separate entities. What fragment should do is to notify its parent activity that some event has happened. But it is, again, NOT a fragment job to decide what to do with that! It should be activity to decide to i.e. replace the fragment on phone, but to i.e. add another to existing one on tablets. So you are basically doing something wrong by design.
And, as others already mentioned, your activity should use FragmentManager ("native" or from compatibility library) to do the job (like replace() or add() or remove()):
http://developer.android.com/guide/components/fragments.html
Just as Marcin said, you shouldn't have a fragment start another fragment or activity. A better way to handle this situation is by creating a callback implementation for the main activity to handle requests such as start a new fragment. Here is a great example in the android developer guide.
There is a way which works; Just (in the fragment) do the following:
getFragmentManager().beginTransaction()
.add(R.id. container_of_this_frag, new MyNewFragment())
.remove(this)
.commit();
When using nested fragments, we don't want every inner fragment replacement goes to the outer most activity. A mechanism allowing a fragment to notify its parent that it wants to change to another fragment can be useful.
Here is my code in Kotlin, I think it is easy to translate into java.
interface FragmentNavigator {
fun navigateTo(fragment: Fragment)
}
class NavigableFragment: Fragment() {
var navigator: FragmentNavigator? = null
override fun onDetach() {
super.onDetach()
navigator = null
}
}
Inner fragments need to extend NavigableFragment, and use following code to change itself to another fragment.
navigator?.navigateTo(anotherFragment)
Outer activities or fragments need to implement FragmentNavigator, and override navigateTo.
override fun navigateTo(fragment: Fragment) {
supportFragmentManager.beginTransaction().replace(view_id, fragment).commit()
}
//Use childFragmentManager instead of supportFragmentManager a fragment
Finally in outer activities or fragments, override onAttachFragment
override fun onAttachFragment(fragment: Fragment?) {
super.onAttachFragment(fragment)
if(fragment is NavigableFragment) {
fragment.navigator = this
}
}
This worked for me:
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MenuFragment()).commit();
For Kotlin.
(activity as YourActivityLauncherFragment)
.supportFragmentManager.beginTransaction()
.replace(R.id.yourFragmentContainer, YourFragmentName()).setReorderingAllowed(true)
.commit()

Is there any way to detect if fragment is showing to user or not?

Here are simple steps.
step1 : fragment1 was showing and it's already added to Backstack
step2 : fragment2 is added to Backstack and showing it now
step3 : fragment2 is removed from Backstack
So finally, fragment1 is showing again to user.
In this situation, is there anyway to detect if fragment1 is showing again inner fragment1?
I tried with OnResume() but it doesn't work.
Thanks for answers!
Fragment currentFragment = getFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment instanceof YourFragment) {
if(currentFragment.this.isVisible())
{
//your code
}
}
When you add the fragment in your transaction you should use a tag.
fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");
...and later if you want to check if the fragment is visible:
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
// add your code here
}
See also http://developer.android.com/reference/android/app/Fragment.html
I just copied this answer https://stackoverflow.com/a/9295085/7232310
because I think is what you need. Otherwise you can check the following answers on the same question.
Hope it helps!
Try onAttach(), this is to trigger if the fragment is showed.
onDetach() is to detect if the fragment is leaving the user interface.
For example: you have 3 fragment(frag1,frag2,frag3), every fragment you need to put the onAttach()
frag1
#Override
public void onAttach(Context context) {
super.onAttach(context);
Toast.makeText(context, "I'm frag 1", Toast.LENGTH_SHORT).show();
}
I think there are 2 options
Try to override this behaviour and see if it works
void onHiddenChanged (boolean hidden)
As per documented here
Or Other option is to onStart() / onResume() callback of lifecycle try to observe behaviour of fragments visibility state.
boolean isVisible ()
As per documented here

How do I figure out what activity is responsible for a fragment?

I have a file fragment_item_attachment.xml which has a <RelativeLayout> and a corresponding ItemAttachmentFragment.java, but how do I figure out what the corresponding activity is? The activities all seem too to be named differently.
It depends which Activity starts the Fragment.
In order to have added the fragment, it's likely you some code similar to:
// Here we have the fragment, but it isn't bound to an activity.
Fragment fragment = new MyFragment();
// Here the fragment will be bound to the activity.
FragmentTransaction transaction = getFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
Once the fragment is bound to the activity, the fragment's getActivity() method will return the activity.
If it isn't bound to an activity, getActivity() will return null.
If you started the fragment from the MainActivity, and you want to access a method in that activity, you could write the following in the fragment:
((MainActivity) getActivity()).myCustomMethod();
To write safer code, avoiding a possible NullPointerException or ClassCastException if the fragment is used in a different way:
if (getActivity() != null && getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).myCustomMethod();
}

To call a method of a fragment from another fragment

I have 2 Fragments for an activity. e.g. FragmentA and FragmentB. I have a public method MethodA in FragmentA. Now I want to use MethodA in FragmentB of FragmentA.
One of the way to do is Create Interface and implement your activity with that interface. Now initilize that interface in FragmentB and on click of something you have to call the method of interface wherever you want to call method of FragmentB. Now in your activity callback method just call the method of FragmentB with the help of object
First you have to get list of all fragment and then child fragment then check your fragment instance.
for (Fragment fragment : getSupportFragmentManager().getFragments())
{
for (Fragment fragment1 : fragment.getFragmentManager().getFragments())
{
if (fragment1 instanceof Shoppingcart)
{
FragmentA mFragmentA = ((FragmentA) fragment1);
mFragmentA.A();
}
}
}

How to replace the activity's fragment from the fragment itself?

My application has a Fragment inside its Activity. I would like to programmatically replace the fragment by another one from the current fragment itself.
For example, if I click on a button inside the fragment, the fragment should be replaced with another one, but the activity should remain the same.
Is it possible? If so, how to do it?
It's actually easy to call the activity to replace the fragment.
You need to cast getActivity():
((MyActivity) getActivity())
Then you can call methods from MyActivity, for example:
((MyActivity) getActivity()).replaceFragments(Object... params);
Of course, this assumes you have a replaceFragments() method in your activity that handles the fragment replace process.
Edit: #ismailarilik added the possible code of replaceFragments in this code with the first comment below which was written by #silva96:
The code of replaceFragments could be:
public void replaceFragments(Class fragmentClass) {
Fragment fragment = null;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment)
.commit();
}
from the official docs:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
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, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
In this example, newFragment replaces whatever fragment (if any) is currently in the layout container identified by the R.id.fragment_container ID. By calling addToBackStack(), the replaced fragment is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.
The behavior you have described is exactly what fragments are designed to do. Please go through the official guide for a thorough understanding of fragments which will clear up all your questions.
http://developer.android.com/guide/components/fragments.html
Please note that fragment should NOT directly replace itself or any other fragments. Fragments should be separate entities. What fragment should do is to notify its parent activity that some event has happened. But it is, again, NOT a fragment job to decide what to do with that! It should be activity to decide to i.e. replace the fragment on phone, but to i.e. add another to existing one on tablets. So you are basically doing something wrong by design.
And, as others already mentioned, your activity should use FragmentManager ("native" or from compatibility library) to do the job (like replace() or add() or remove()):
http://developer.android.com/guide/components/fragments.html
Just as Marcin said, you shouldn't have a fragment start another fragment or activity. A better way to handle this situation is by creating a callback implementation for the main activity to handle requests such as start a new fragment. Here is a great example in the android developer guide.
There is a way which works; Just (in the fragment) do the following:
getFragmentManager().beginTransaction()
.add(R.id. container_of_this_frag, new MyNewFragment())
.remove(this)
.commit();
When using nested fragments, we don't want every inner fragment replacement goes to the outer most activity. A mechanism allowing a fragment to notify its parent that it wants to change to another fragment can be useful.
Here is my code in Kotlin, I think it is easy to translate into java.
interface FragmentNavigator {
fun navigateTo(fragment: Fragment)
}
class NavigableFragment: Fragment() {
var navigator: FragmentNavigator? = null
override fun onDetach() {
super.onDetach()
navigator = null
}
}
Inner fragments need to extend NavigableFragment, and use following code to change itself to another fragment.
navigator?.navigateTo(anotherFragment)
Outer activities or fragments need to implement FragmentNavigator, and override navigateTo.
override fun navigateTo(fragment: Fragment) {
supportFragmentManager.beginTransaction().replace(view_id, fragment).commit()
}
//Use childFragmentManager instead of supportFragmentManager a fragment
Finally in outer activities or fragments, override onAttachFragment
override fun onAttachFragment(fragment: Fragment?) {
super.onAttachFragment(fragment)
if(fragment is NavigableFragment) {
fragment.navigator = this
}
}
This worked for me:
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MenuFragment()).commit();
For Kotlin.
(activity as YourActivityLauncherFragment)
.supportFragmentManager.beginTransaction()
.replace(R.id.yourFragmentContainer, YourFragmentName()).setReorderingAllowed(true)
.commit()

Categories

Resources