Reputation:
I am currently making an android app, and I want to pass a date between activity and fragment. My activity has a button, which opens the fragment: DatePickerFragment.
In my activity I show a date, which I want to modify with the fragment. So I want to pass the date to the datepicker, and send it back to the activity.
I've tried a lot of solutions, but none are working. The easy way would pass an argument, but this can't be done with fragments.
Upvotes: 157
Views: 191842
Reputation: 41
answering in 2021 now a days fragment has in built static methods which are used to pass arguments while creating the fragment try them future coders
when you create a fragment it has the following static method with already defined
public static categoryfrag newInstance(String param1, String param2) {
categoryfrag fragment = new categoryfrag();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
onCreate method in fragment receives parameters through already defined code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
// rr=getArguments().getInt("ky");
sn1=mParam1;
sn2=mParam2;
}
}
the below code is used in activity where mostpop is the name of the fragment class if you want other datatypes modify this in-built lines or use bundle
Fragment mp=mostpop.newInstance("parameter1","parameter2");
Upvotes: 4
Reputation: 1
Public variable declarations in classes is the easiest way:
On target class:
public class MyFragment extends Fragment {
public MyCallerFragment caller; // Declare the caller var
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Do what you want with the vars
caller.str = "I changed your value!";
caller.i = 9999;
...
return inflater.inflate(R.layout.my_fragment, container, false);
}
...
}
On caller class:
public class MyCallerFragment extends Fragment {
public Integer i; // Declared public var
public String str; // Declared public var
...
FragmentManager fragmentManager = getParentFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
myFragment = new MyFragment();
myFragment.caller = this;
transaction.replace(R.id.nav_host_fragment, myFragment)
.addToBackStack(null).commit();
...
}
If you want to use the main activity it is easy too:
On main activity class:
public class MainActivity extends AppCompatActivity {
public String str; // Declare public var
public EditText myEditText; // You can declare public elements too.
// Taking care that you have it assigned
// correctly.
...
}
On called class:
public class MyFragment extends Fragment {
private MainActivity main; // Declare the activity var
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Assign the main activity var
main = (MainActivity) getActivity();
// Do what you want with the vars
main.str = "I changed your value!";
main.myEditText.setText("Wow I can modify the EditText too!");
...
return inflater.inflate(R.layout.my_fragment, container, false);
}
...
}
Note: Take care when using events (onClick, onChanged, etc) because you can be on a "fighting" situation where more than one assign a variable. The result will be that the variable sometimes does not will change or will return to the last value magically.
For more combinations use your creativity. :)
Upvotes: -2
Reputation: 5770
For all the Kotlin developers out there:
Here is the Android Studio proposed solution to send data to your Fragment (= when you create a Blank-Fragment with File -> New -> Fragment -> Fragment(Blank) and you check "include fragment factory methods").
Put this in your Fragment:
class MyFragment: Fragment {
...
companion object {
@JvmStatic
fun newInstance(isMyBoolean: Boolean) = MyFragment().apply {
arguments = Bundle().apply {
putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean)
}
}
}
}
.apply
is a nice trick to set data when an object is created, or as they state here:
Calls the specified function [block] with
this
value as its receiver and returnsthis
value.
Then in your Activity or Fragment do:
val fragment = MyFragment.newInstance(false)
... // transaction stuff happening here
and read the Arguments in your Fragment such as:
private var isMyBoolean = false
override fun onAttach(context: Context?) {
super.onAttach(context)
arguments?.getBoolean("REPLACE WITH A STRING CONSTANT")?.let {
isMyBoolean = it
}
}
To "send" data back to your Activity, simply define a function in your Activity and do the following in your Fragment:
(activity as? YourActivityClass)?.callYourFunctionLikeThis(date) // your function will not be called if your Activity is null or is a different Class
Enjoy the magic of Kotlin!
Upvotes: 11
Reputation: 3323
Sending data from Activity into Fragments linked by XML
If you create a fragment in Android Studio using one of the templates e.g. File > New > Fragment > Fragment (List), then the fragment is linked via XML. The newInstance method is created in the fragment but is never called so can't be used to pass arguments.
Instead in the Activity override the method onAttachFragment
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof DetailsFragment) {
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
}
}
Then read the arguments in the fragment onCreate method as per the other answers
Upvotes: 4
Reputation: 5666
To pass info to a fragment , you setArguments when you create it, and you can retrieve this argument later on the method onCreate or onCreateView of your fragment.
On the newInstance function of your fragment you add the arguments you wanna send to it:
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
Then inside the fragment on the method onCreate
or onCreateView
you can retrieve the arguments like this:
Bundle args = getArguments();
int index = args.getInt("index", 0);
If you want now communicate from your fragment with your activity (sending or not data), you need to use interfaces. The way you can do this is explained really good in the documentation tutorial of communication between fragments. Because all fragments communicate between each other through the activity, in this tutorial you can see how you can send data from the actual fragment to his activity container to use this data on the activity or send it to another fragment that your activity contains.
Documentation tutorial:
http://developer.android.com/training/basics/fragments/communicating.html
Upvotes: 240
Reputation: 161
You can simply instantiate your fragment with a bundle:
Fragment fragment = Fragment.instantiate(this, RolesTeamsListFragment.class.getName(), bundle);
Upvotes: 0
Reputation: 126445
Activity
to a Fragment
Activity:
Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();
Fragment:
Reading the value in fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String myValue = this.getArguments().getString("message");
...
...
...
}
But if you want to send values from Fragment to Activity, read the answer of jpardogo, you must need interfaces, more info: Communicating with other Fragments
Upvotes: 100
Reputation: 691
Use the library EventBus to pass event that could contain your variable back and forth. It's a good solution because it keeps your activities and fragments loosely coupled
https://github.com/greenrobot/EventBus
Upvotes: 5