I've been doing it like this for a while, is it the right way?
Activity:
public void toSettings(){
Fragment_Settings frag = new Fragment_Settings();
fm.beginTransaction()
.replace(R.id.mainContainer, frag)
.addToBackStack(null)
.commit();
}
In some listener in another fragment:
((Activity_Main)getActivity()).toSettings();
You don't need .addToBackStack(null) Just delete that piece and your fragment will not be added to backstack. I would also suggest adding a TAG to the replace method just in case you want to retrieve the fragment later. Something like this .replace(R.id.mainContainer, frag, TAG).
It seems correct but i have some suggestions.
If you wanna back previous fragment from Fragment_Settings use add method instead of replace and addToBackStack("tag of Fragment_Settings") instead of addToBackStack(null).
newInstance pattern is more preferred than Fragment_Settings frag = new Fragment_Settings();. You can see some explanations about that.
http://www.androiddesignpatterns.com/2012/05/using-newinstance-to-instantiate.html
Creating a Fragment: constructor vs newInstance()
To avoid code repetition when navigating between fragments you can use a manager class provides organizing add, replace or pop processes.
Here is my navigation manager class.
Related
I have added a fragment in another fragment
in this way
Secondfragment secondFragment=new SecondFragment(parmater);
fragmentManager.beginTransaction()
.replace(fragmentContainerView.getId(),
secondFragment, null)
.setReorderingAllowed(true)
.commit();
the firstFragment is containing the fragmentContainerView and it's inside a ViewPager2 with other fragments
after changing the page and return to it again the app is crashes and give me the error
Unable to instantiate fragment , as I mentioned this because the firstFragment have a parameter in constructor .
I use this way in multiple places .
after changing the page the first fragment is been in the onPause state and after I go to the first fragment again its recreate the views and the proplen happen here , it cannot instantiate the second fragment.
I want a way to let it instantiate it again ,or any better idea and thank you in advance .
I've been looking for a solution to do this but I couldn't find it.
I have a DialogFragment called ImportDialog, with a tag of the same name. How could I get this ImportDialog instance from my MainActivity?
Try this
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment frg= getFragmentManager().findFragmentByTag("dialog");
if (frg!= null) {
ft.remove(frg);
}
ft.addToBackStack(null);
DialogFragment newFragment = MyDialogFragment();
newFragment.show(ft, "dialog");
Is this how you opted your code?:
(ImportDialog) getFragmentManager().findFragmentById([ID of layout here]);
I think it would help if you instantiated the Fragment or at least have it inflated. Only then will findFragmentById() work.
But then again, I did read that there are work arounds to this, such as using the findFragmentByTag Option if you haven't looked into that:
YourFramgent yourFragment = new YourFragment();
fragmentTransaction.add(R.id.fragment_container, myFragment, "yourFragment");
fragmentTransaction.commit();
And then to call it:
YourFragment yourFragment = (YourFragment) getFragmentManager().findFragmentByTag("yourFragment");
I solved this by adding an interface in my MainActivity and implementing it on my DialogFragment, that way I can pass data from the MainActivity to the Dialog.
As per the official Android documentation, "commit" is an asynchronous operation.
Calling commit() doesn't perform the transaction immediately. Rather, the transaction is scheduled to run on the main UI thread as soon as it is able to do so. If necessary, however, you can call commitNow() to run the fragment transaction on your UI thread immediately.
Hence if you want to get an instance of the fragment immediately after adding or replacing it to the container, then you should use "commitNow" instead of "commit". An example is shown below.
RetryDialogFragment().showNow(childFragmentManager, RetryDialogFragment.TAG)
val retryDialogFragment =
childFragmentManager.findFragmentByTag(RetryDialogFragment.TAG) as RetryDialogFragment
However, you must also be mindful of the following fact when using commitNow.
Note that commitNow is incompatible with addToBackStack. Alternatively, you can execute all pending FragmentTransactions submitted by commit() calls that have not yet run by calling executePendingTransactions(). This approach is compatible with addToBackStack.
For more reference on the same, checkout : Commit is asynchronous
I am trying to use the searchview in the toolbar (menu) in multiple fragments. So, if I switch to various fragments, the searchview would apply to and search only that fragment then. After defining it in the MainActivity, how do I use it in the fragments?
You should keep reference to your fragments like you want. Then depending from your situation, when you typing the request or any other way, you need to make search in your fragment, like this:
myFragment.doSearch(query)
If you have a list of frargments and you need to make a call only in currently visible, you can define the isActuallyVisible variable in each fragment(on in BaseFragment if you have one) and change it like this:
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
isActuallyVisible = visible;
}
Then you can make search like this:
for (Fragment frag : fragmentsList) {
if (frag.isActuallyVisible) {
frag.doSearch(query);
break;
}
}
Hope this will help you to find the correct solution
I have a nested Fragment with a Viewpager inside of it. I'm trying to access a method (using MainActivity) in one of the Viewpager's Fragments, but I only get the last Viewpager Fragment or can't access methods when I use
ProfileFragment f = (ProfileFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentLayout);
...
Fragment f = v.getChildFragmentManager().findFragmentById(R.id.pager);
// Doesn't even work when I use findFragmentByTag("TAG")
where 'fragmentLayout' is the container for my Fragment Transactions inside activity_main.xml. (Currently ProfileFragment inside)
Here is how I nested my Fragments/xml:
MainActivity
- fragmentLayout
- ProfileFragment (or LoginFragment/ChatFragment/ShopFragment/etc)
- xml items
- viewPager
- Fragment1
- Fragment2 // can't access methods in here from MainActivity
- navigationTabs
I tried getting the Viewpager & PageAdapter from ProfileFragment and it shows the correct number of fragments, but I can't seem to access the methods.
Would an interface be something to look into? Or is there an easier way? Thank you.
String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
return fragment;
((YourFragment)fragment).methodName();
Try this
There are 2 simple ways to do it:
Store your Fragment1 and Fragment2 in your ProfileFragment, then when you need to call there's function, just call fragment1.doSomeThing() from your ProfileFragment. This approach is ok when your ViewPager's adapter dont have too many fragments (in this case, you should use WeakReference to avoid OOM when storing your fragments`.
Using EventBus (or LocalBroadCastReceiver, but I prefer EventBus). Then you can call your doSomeThing() function from anywhere, with the call like below:
EventBus.getDefault().post(new CallYourFunctionObject(int value)
None of the solutions worked for me & I had trouble implementing an interface with my nested fragments.
I ended up putting the methods in MainActivity which was the easiest solution for me.
I can also access the nested fragment views directly from MainActivity with
TextView tv1 = findViewById(R.id.exampleid);
So currently I have a application with different activities, and I use buttons to navigate between activities. I later decided that I should add the navigation drawer and use fragments instead. So one of my fragments has a bunch of fields that the user fills out that I need to pass onto the next fragment. So my question is, Do I keep all the work in activities and call the activity from the fragment? Or do I just include all he java in my activity in the java for the fragment? For the most part I am taking the fields from the first fragment, and I'd like to pass the values to the next fragment so it can handle some calculations.
final EditText FinalPriceText = (EditText) v.findViewById(R.id.editTextPrice);
final EditText TradeInPriceText = (EditText) v.findViewById(R.id.editTextTrade);
i.putExtra("FinalAutoPrice", FinalAutoPriceText.getText().toString());
i.putExtra("TradeInPrice", TradeInPriceText.getText().toString());
startActivity(i);
As far as calculations go, if you are going to use them a lot and they have nothing to do with the activity or android lifecycle I would separate them out into a different class and then you can call them from anywhere.
If they do rely on the activity you could still separate them out but pass a reference to the activity when doing your calculations. You can get the parent activity by calling this.getActivity() from any fragment
You can cast this.getActivity() to whatever the parent activity is and you can call the methods from that object as well. This works fine but your fragment will only work with the activity you specify and it can get sloppy if you are not careful.
Otherwise put them in the fragment where you need them. I would consider this least recommended if you need to use calculations anywhere else in the app. Duplicate code is just asking for bugs in the future.
As far as passing data, create a static instance method in fragment2 and pass it what you need there.
For example
public Fragment2 extends Fragment {
public static fragment2 newInstance(MyData myDataIPass) {
Fragment2 fragment = new Fragment2();
Bundle args = new Bundle();
args.putInt("someInt", myDataIPass.someInt);
fragment.setArguments(args);
return fragment;
}
}
Call this new instance method when creating your fragment transaction like this
FragmentManager fm = getActivity().getFragmentManager();
fm.beginTransaction()
.replace(R.id.container, Fragment2.newInstance(MyData myDataIPass))
.commit();
Well, you have mainly two options here:
use Intent.putExtra() with fragments. Just like Activities, you
can use this method with Fragments as well. See the following links
for the implementation in Fragments
this
this
The other option is to use SharedPreferences and store data as key value pairs from one fragment, and can be accessed from any other activity/fragments. See this nice tutorial to understand better!
You have a special callback in Fragment to get Activity.
It is called:
#Override
public void onAttach(Context context) {
super.onAttach(context);
YourActivity activity = (YourActivity) context;
}