How to Pass a Variable from Activity to Fragment, and Pass It Back

How to pass Arguments to Fragment from Activity

It's hard to say without seeing the logcat, but surely you are missing to call the commit() method on the FragmentTransaction. Also remember to set the arguments to the fragment before calling ft.commit().

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
mFragment = (LayoutFragment) getSupportFragmentManager().findFragmentByTag(mTag);

if (mFragment == null) {
Bundle bundle = new Bundle();
bundle.putInt("noTiles", 4);
mFragment = (LayoutFragment) LayoutFragment.newInstance(mLayoutId);
mFragment.setArguments(bundle);
//ft.add(R.id.content, mFragment, mTag).commit();
ft.add(R.id.content, mFragment, mTag);

} else {
ft.attach(mFragment);
}

mSelectedLayoutId = mFragment.getLayoutId();
}

Passing values from Activity to Fragment

You need to create a function in your Profile fragment called newInstance that creates the fragment and set the arguments through there, then returns the fragment with the arguments. Like this

public static Profile newInstance(String name){
Profile profile = new Profile();
Bundle bundle = new Bundle();
bundle.putString("name", name);
profile.setArguments(bundle);
return profile;
}

Then create the fragment in your activity like this

Profile profile = Profile.newInstance(gname);

And get the arguments how you have been doing in the onCreate in the fragment.

You also should be creating the Fragment in the activity you are using it in. So if it's in your home activity you will want to pass the data from the login activity, then build the fragment in the onCreate for the home activity.

Intent home = new Intent(this, HomeActivity.class);
intent.putExtra("name", gname);
startActivity(home);

in the HomeActivity

Bundle extras = getIntent().getExtras();
String gname = extras.getString("name");
Profile profile = Profile.newInstance(gname);

Passing Value from Activity to Fragment

You can go many ways but given your current implementation (using a newInstance), I'd go with using your parent activity as a mediator, going like this:

1) Create a BaseFragment class which your TestFragmentOne and TestFragmentTwo will extend and in there hold a reference to your parent Activity (here named "MainActivity"):

abstract class BaseFragment : Fragment() {

lateinit var ACTIVITY: MainActivity

override fun onAttach(context: Context) {
super.onAttach(context)
ACTIVITY = context as MainActivity
}
}

2) Then, in your Activity make sure you declare your variable as a field:

class MainActivity : AppCompatActivity() {

var textVariable = "This to be read from the fragments"
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
textVariable = "I can also change this text"
...
}
}

3) Then, from each fragment you can access your variable using the instance inherited from your BaseFragment:

 class TestFragmentOne : BaseFragment() {

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val incomingText = ACTIVITY.textVariable
println("Incoming text: "+incomingText)

// You can also set the value of this variable to be read from
// another fragment later
ACTIVITY.textVariable = "Text set from TestFragmentOne"
}
}

Send data from activity to fragment in Android

From Activity you send data with intent as:

Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

and in Fragment onCreateView method:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}

How do I pass the variables of an activity to the fragments of a BottomNavigationView?

There is no direct access to HomeFragment from MainActivity in your case. BottomNavigation uses nested navigation architecture pattern with nested graphs.
More details here: Passing argument(s) to a nested Navigation architecture component graph

But you can use alternative way to pass data from Activity to Fragment using context.

Step 1 - Describe HomeFragmentData model:

data class HomeFragmentData(
val value: String
)

Step 2 - Describe HomeFragment interface:

interface IHomeFragment {
fun getHomeFragmentData(): HomeFragmentData
}

Step 3 - Implement interface to your Activity:

class MainActivity : AppCompatActivity(), IHomeFragment {

override fun getHomeFragmentData(): HomeFragmentData {
return HomeFragmentData(
value = "Home Fragment data"
)
}

// Rest of your code
}

Step 4 - Call function getHomeFragmentData() from HomeFragment using context:

class HomeFragment : Fragment() {
private var interactionListener: IHomeFragment? = null

override fun onAttach(context: Context) {
super.onAttach(context)

when(context) {
is IHomeFragment -> {
interactionListener = context
}
else -> throw RuntimeException("$context has to implement IHomeFragment")
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
interactionListener?.getHomeFragmentData().let {
textView.text = it?.value
}

return root
}
}

How to pass and get value from fragment and activity

Here is the Android Studio proposed solution (= 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 returns this 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
}
}

Enjoy the magic of Kotlin!



Related Topics



Leave a reply



Submit