So basically I'm using same type of fragment in two different activities and I want to create and initialize some variable in the fragment only if it was added from specific activity. My question is how can I programmatically find out in which activity the fragment was added.
there're two main ways of achieving it:
the less modular approach, you simply check using instanceof
if(getActivity() instanceof MyActivity)
and the more modular approach, you pass some arguments to the fragment on the moment you'll add it to the transaction:
// this during the transaction to pass extra parameters to the fragment
Fragment f = new MyFragment();
Bundle b = new Bundle();
b.putBoolean("doExtraCode", true);
f.setArguments(b);
then inside the fragment:
// check if should execute extras
Bundle b = getArguments();
boolean doExtraCode = b == null? false: b.getBoolean("doExtraCode", false);
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);
}
I have an activity that calls to a web service and I want to pass these result to a fragment. Obviously the web service is invoked by an AsyncTask, so the fragment is loaded before getting result.
How can I pass this paramteter from activity's AsyncTask to fragment when is received?
You can implement a method inside your Fragment and call it when needed. For bidirectional communication between an Activity and a Fragment see http://developer.android.com/training/basics/fragments/communicating.html
Set bundle in your fragment.
Bundle args = new Bundle();
args.putInt("id",value);
Fragment newFragment = new Fragment();
newFragment.setArguments(args);
In your fragment get the bundle as
Bundle b = getArguments();
String s = b.getInt("id");
You could move the AsyncTask into the fragment.
But if you wish to keep your current set up, you should save the Fragment reference when you initialize it, and create a public function in the fragment that takes the new data as a parameter.
So the activity code could look like this:
MyFragment fragment = new MyFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commit();
and then you could call:
fragment.updateData(myNewData);
Just make sure to do the appropriate null-checks, just to be safe.
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.
I want to pass arguments from my activity to a fragment, embedded into the activity. Fragment is embedded statically in xml layout.
I tried to call setArgument() like this:
setContentView(R.layout.detail_activity);
DetailFragment detailFragment = (DetailFragment) getFragmentManager().findFragmentById(R.id.detailFragment);
detailFragment.setArguments(getIntent().getExtras());
but it is already too late, because setArguments has to be called immediately after fragment's creation. The only was I see it to getArguments() and the change the bundle. Any better way?
AFAIK, you can't use setArguments() like that when you embed the fragment within XML. If it's critical, you'd be better off dynamically adding the fragment instead. However if you truly want the fragment to be embedded via XML, there are different ways you can pass along that data.
Have the Activity implement the fragment's event listener. Have the fragment then request the required parameters from the Activity at creation or whenever needed. Communication with Fragment
Create custom attributes that can be embedded in xml along with the fragment. Then during fragment's inflation process, parse the custom attributes to obtain their data. Custom fragment attributes
Create public setters in the fragment and have the activity use them directly. If it's critical to set them prior to the fragment's onCreate() method, then do it from the activity's onAttachFragment() method.
You have two options here
If you just need information in the activity's intent, then placing information from the intent into the fragment arguments just adds an unneeded step. You might just a well keep things simple and from your fragment call
Bundle data = getActivity().getIntent().getExtras();
If you need to add information that is not in the activity's intent then in you fragment create a no parameter constructor like:
public DetailFragment() {
this.setArguments(new Bundle());
}
then in your activity you can add whatever arguments you need with code like:
DetailFragment frg = (DetailFragment) getFragmentManager().findFragmentById(R.id.detailFragment);
frg.getArguments().putBundle("key", data);
the point here is to use the existing bundle object rather than trying to call setArguments() after the fragment has been attached to the activity.
Another way to pass data to Fragment is as following:
//In DetailFragment (for Instance) define a public static method to get the instance of the fragment
public static final DetailFragment getInstance(Bundle data) {
DetailFragment fragment = new DetailFragment();
fragment.setArguments(data);
return fragment;
}
And when attaching DetailFragment from inside Activity
Bundle data = new Bundle();
//Add data to this bundle and pass it in getInstance() of DetailFragment
fragmentTransaction.replace(R.id.frament_layout, DetailFragment.getInstance(data));
I currently have this Custom ArrayList:
ArrayList<PlaceDetails> place_list = new ArrayList<PlaceDetails>();
which will be populated during the onCreateView() portion.
I am unsure as of how do I pass this ArrayList in a bundle from this fragment class to another fragment class. Below is the snippet of my codes:
public void Map(View view){
if(hasConnection() == true){
Bundle b = new Bundle();
// how should I be passing the ArrayList in this bundle?
FragmentTransaction ft = getSherlockActivity().getSupportFragmentManager().beginTransaction();
TOnlineMapViewFragment mapfrag = TOnlineMapViewFragment.newInstance(b);
ft.replace(R.id.container, mapfrag).addToBackStack(null).commit();
}
}
So I've created the bundle and I wanted to pass it to the next fragment with the newInstance() method. How should I do this?
Consider implementing Parcelable interface in your classes. Then you would be able to store PlaceDetails in Bundle and pass it to setArguments() method.
I've found a tutorial: http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/
I haven't testes it but it looks good.
Are you really sure a bundle is really needed?
TOnlineMapViewFragment mapfrag = TOnlineMapViewFragment.newInstance(b);
mapfrag.setPlaceList(place_list)
Should be trivial to create setPlaceList(ArrayList<PlaceDetails> place_list) ...