i have a internal discussion about what way is better to share info between fragments contents inside a controller activity. In a first classical way, you can set arguments when you are going to replace fragments as follows:
//Just now i'm inside Fragment 1 and i'll navigate to Fragment 2
Fragment newFragment = getFragmentManager().findFragmentByTag(Fragment2.TAG);
Bundle b = new Bundle();
b.putBoolean("test1", true);
// Create new fragment and transaction
if(newFragment==null)
newFragment = Fragment2.newInstance(b);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)//.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim)
.replace(R.id.fragment_place, newFragment, Fragment2.class.getName())
.addToBackStack(newFragment.getClass().getName())
.commit();
The newInstace method does as i meant above, so, with setArguments:
public static Fragment2 newInstance(Bundle arguments){
Fragment2 f = new Fragment2();
if(arguments != null){
f.setArguments(arguments);
}
return f;
}
But Fragment1 and Fragment2 they are both inside a ControllerActivity, so i can also think about a second way to share information obtained in Fragment1 towards Fragment2, through declaring attributes in the ControllerActivity, so i could do (declaring previously an object in the activity) as follows inside any fragment:
EDIT
public class ControllerActivity extends FragmentActivity{
int value = 5;
...
And then, inside my fragment:
((SplashActivity)getActivity()).value = 10; //i can assign or recover value when i desire
My question is what inconveniences would have doing as the second way.
Writing code using 2nd way is fast. But the problem is you have to cast the general Activity to the more specific SplashActivity in which the value variable exists. If you want to use the Fragment with another Activity, or you want a Fragment to be a general purpose UI component you have to use interface for passing the data.
As mentioned in comments, bellow links provide more details about interface/callback method:
android docs
video from slidenerd
Hope this answers your question.
Related
I am trying to send a data from MainActivity (on MenuItem click) to a Fragment of its Child Fragment.
I have shown an image to understand better.
I want an event to be fired in DayFragment from the MainActivity when MainActivity menuclicked.
I cannot send when the fragment is being created as you know.
Any ideas (or) code to understand the idea would be helpful.
Guys, Negative vote would neither help you nor me.
I will explain in little detail.
I am going to show a datepicker dialog fragment on menu item click on MainActivity. I need to pass the date from MainActivity -> calendarfragment - > dayfragment.
I want the date in dayfragment to other process. Thats it.
Create a public method inside Fragment which the Activity will call upon item selection.
From that public method, using the instance of ChildFragment, call another public method inside ChildFragment to make the magic happen!
You can use Fragment.setTarget(Fragment fragment, int requestCode); , just in case
Use a Bundle. Here's an example:
Fragment fragment = new Fragment(); // replace your custom fragment class
Bundle bundle = new Bundle();
FragmentTransaction fragmentTransaction = getSupportFragmentManager(). beginTransaction();
bundle.putString("key","value"); // use as per your need
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(viewID,fragment);
fragmentTransaction.commit();
Bundle has put methods for lots of data types.
Then in your Fragment, retrieve the data (e.g. in onCreate() method) with:
Bundle bundle = this.getArguments();
if (bundle != null) {
int myInt = bundle.getInt(key, defaultValue);
}
Hey I was wondering how I could transfer data from one activity to a fragment using fire base. I have edit text in the activity class and a list view in the Fragment.
I would like to display the information throughout the app database so that other users can see and edit the information too.
I dont know if the IDE matters but passing information to a fragment is usually done with fragment arguments. You need to create a static "newInstance" method in your fragment that you can call from the activity and pass whatever info to the fragment through it. Something like this:
public static mListFragment newInstance(String fromActivity) {
mListFragment fragment = new mListFragment ();
Bundle args = new Bundle();
args.putString("STIRNG_FROM_ACTIVITY", fromActivity);
fragment.setArguments(args);
return fragment;
}
You can then call the method from the activity like this:
FragmentManager fm = getFragmentManager().beginTransaction();
mListFragment fragment = new mListFragment();
fragment = mListFragment.newInstance("info_to_send");
fragmentTransaction.add(R.id.fragments_frame, fragment);
From here you can even persist the info across device screen orientation changes..
Just use firebaseRef to setValue() and set the value from the edittext.
Add ValueListener on the fragment to get the same value from dataSnapshot.
:D
https://github.com/firebase/quickstart-java/tree/master/database/src/main/java/com/google/firebase/quickstart
I am using navigation drawer and it is simple to use. I am not providing the complete code but providing you detail which could be easy for you to understand my problem. I am using fragments these are about 8 in numbers and I am replacing them with one an other. But here comes a problem
I am replacing them on click event of the navigation drawer. but there are two main problems
After replacement , I can see the previous fragment in the background. does replace method just call the new fragment over it ? if yes then what should I do to old fragment not be visible in the background of my new fragment.
When I click navigation drawer Item , it loads the specific fragment successfully. but keeping in that fragment when I click to that specific item again it loads this fragment again and again. For example if drawer item num 3 opens fragment MyBook , then by clicking item num three 2 or many times would open fragment that much time.
So please some one answer me how to cure my app for such kind of actions which I described above.
I tried like this. Its working fine me
FragmentManager frgmanager = getFragmentManager();
frgmanager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction frgTransaction = frgmanager.beginTransaction();
if(subitem.equalsIgnoreCase("subitem")){
Frag1 frg1 =new Frag1(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg1);
}else if(subitem1.equalsIgnoreCase("subitem1")){
Frag2 frg2 =new Frag2(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg2);
}else{
Frag2 frg3 =new Frag3(mCtx);
frgTransaction.replace(R.id.inflate_layout, frg3);
}
frgTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
frgTransaction.commit();
you can use addtobackstack in fragmentstranstion object.like
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.addtoBackStack(null).commit();
Use replace-method of FragmentTransaction instead of add (http://developer.android.com/guide/components/fragments.html#Transactions)
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.bodyfragment, new AnotherFragment());
transaction.commit();
To avoid re-instantiating the fragment, keep track of the current open fragment and only do a fragment transaction, if we next-to-be-opened fragment is a different one than the current.
This may achieved like the following:
class MyActivity ... {
private String currentFragment;
private void openNewFragment(Fragment fragment) {
String newFragment = fragment.getClass().getSimpleName();
if (newFragment.equals(currentFragment)){
// new fragment already shown
return;
}
// Fragment transaction etc here:
}
}
Note that this only compares fragments based in their class name. Sometimes this might not be unique, e.g. if there is a DetailFragment class which displays information about an entity. Which entities details to show may depend on intent arguments.
The above code however will then prevent opening DetailFragment for Entity=1 if currently details for Entity=2 are shown. For these scenarios the information about the fragment kept needs to be extended (e.g. storing a Reference or WeakReference to the fragment instance itself).
I have an Activity with ListView, when clicking on a list item opens a new fragment.
Do I need to create a new fragment every time like this?
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.root_layout,new MyFragment());
Or will be enough to create a fragment once and then use it?
in activity:
MyFragment myFragment = new MyFragment();
......
in onItemClickListener:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.root_layout,myFragment);
It depends on your case. In most cases every list item opens a different fragment (with different data). Then you have to make a static newInstance(Data mySerializableData) method in your fragment, use default constructor inside of it, pass data over Fragment arguments See DetailFragment and use fragmentTransaction.replace() in your activity to add this fragment.
When you dont want your fragment to be changed you can create it only once as you say but there is no need of adding it on every item click. So one creation and only one add.
No, you don't need to create it every time. First, instead of using "add", use "replace". If there is no fragment in fragment manager, your fragment will be added, instead it will be replaced. If you use "add", then you could accidentally add more than one fragment.
You should check for the fragment in the fragment manager and call methods for content updates.
Example:
myFragment = (MyFragment) fragmentManager.findFragmentById(R.id.my_fragment);
if (myFragment == null) {
myFragment = MyFragment.getInstance(someDataIfNeeded);
fragmentManager.beginTransaction().replace(R.id.my_fragment, myFragment).commit();
} else {
myFragment.updateFragmentContent(someData);
}
check instance of that fragment everytime like this-
In your fragment class -
public static final MyFragment newInstance()
{
MyFragment f = new MyFragment();
return f;
}
and in your activity when you want to create fragment -
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.root_layout,MyFragment.newInstance());
this is well n good manner...
My question is not easy to describe, but I will do my best:
On my tablet-app I have one activity with a listFragment A on left side and a detailFragment B on right side. So when I click an item on the list, the detailFragment shows the proper details of the chosen (list) item.
Now when I click a button on my detailFragment B. the fragment gets swapped with a new Fragment from type infoFragment. The listFragment on left side stays as it is.
So now, when I click another item on the List, I want the infoFragment to vanish and get a detailFragment once again.
My problem is, that i need some kind of check if currently there is an infoFragment or a detailFragment displayed. So that I can either just refresh the detailFragment OR stop the infoFragment and build a new detailFragment.
idea:
if ( //detailFragment is active ) {
updateContent();
}
else {
FragmentManager.buildDetailFragment();
}
have been fiddling for hours now, any help is appreciated!!
How can i figure it out whether there is a detailFragment or listFragment displayed?
edit:
i change my detailFragment with the infoFragment here:
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.details_fragment);
fragment = new InfoFragment();
fm.beginTransaction()
.replace(R.id.details_fragment, fragment)
.commit();
When you add a Fragment to your fragment manager with a FragmentTransaction you can specify a key value. You can then findFragmentByTag which will determine if the Fragment with that key value has been added to the fragment manager.
So long as you are not using a ViewPager or some other structure where multple fragments are added at once, searching for whether your fragment manager contains a fragment by tag will let you know which is currently displayed. You can then use the results of that search to update the fragment since the result is a reference to the fragment itself.
This means you can pass data from the FragmentActivity to the fragment directly by calling any publicly accessable fragment methods. For example
Fragment displayedFragment = fragmentManager.findFragmentByTag(TAG);
if(displayedFragment != null){ //null if no fragment with tag value
displayedFragment.updateList() //public method within fragment
}
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment.isVisible()) {
// add your code here
}
From Here
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.content_id);
now we can get the fragment name by getClass
fragment.getClass().getSimpleName()
You can get class of fragment and check which one it exactly is by calling getClass().