I have a SherlockFragmentActivity with two SherlockFragment in ActionBar.
In each SherlockFragment I ask for several values to user like Step 1 and Step 2 task. In Step 2 Fragment, I have a button that calls webMethod in order to do action but for this webMethod I need all values that user introduced in Step 1 & 2 Fragments.
What is the best practice to pass or get the Step 1 fragment values in Step 2 fragment?
Create a Bundle Object and put Values in the bundle and pass that to next fragment using setArguments().
Bundle b = new Bundle();
b.putString("myString","String Value");
b.putInt("myInt",9);
yourFragment.setArguments(b);
Then you retrieve the same in Second Fragment as
Bundle b = getArguments();
String myStringFromFirstFragment = b.getString("myString");
int myIntFromFirstFragment = b.getInt("myInt");
You can pass values between Fragments through your SherlockFragmentActivity. The main idea is to create an interface and make your activity implement this one to pass data from fragmentA to Activity and from this one to your other fragmentB.
Check out Communicating with activity and Creating event callbacks to the activity in Android docs for more detailed information.
Hope this helps.
Related
My android application have BottomNavigationBar. It contains 5 fragments. One of its fragment contain nested fragment which is mutiple step process.
first nested fragment contain next button.Second nested fragment contain previous and next button.Third nested fragment contain previous and submit button. Each fragment have different EditText.
After adding the values in first fragment, when i click next button it goes to second fragment. In second fragment when i click previous button it goes to first fragment again and same process applies to second and third fragment
My questions is:
1)When previous button in second fragment is clicked, i want all the values of EditText in first fragment as it is and when again next button of first fragment is clicked, i want all the values of EditText in second fragment as it is. Is there any way to do this?
2)I want all the EditText values of all nested fragments when user clicked on submit button in third fragment.How to do that?
Yes,
This can be achieved using two ways,
1) Fragment savedInstanceState
https://stackoverflow.com/a/17135346/7316675
2) Keep you values stored at some activity or application level, and access it on resume of fragment screen
You could use a Bundle to store the values and then restore them when you restore the fragment. You could either do this in onStop() (recommended) or onPause().
Private static final String KEY_ADDRESS = "ADDRESS" ;
#Override
Public void onstop(){
Bundles state = new Bundle ();
String address = etv1.getText().toString();
// Get more strings from the etvs
state.putString(KEY_ADDRESS, address);
// Store more strings into the bundle
setInitialSavedState(state)
}
To restore the values you use either the saved instance state the system passed to onCreate() , or pass the bundle to a self created public bundle in onCreate() and access in onResume() like so:
String address = bundle.getString(KEY_ADDRESS);
As for the results being passed you could communicate the bundles to their parent activity whenever the next or previous button is pressed and do with it as you please when submit is pressed. Learn more on How to do that from the docs or this answer on how to do that
Solution of my first question.
I have used popBackStack() method of FragmentManager. Using this i can go back to the previous fragment of stack.I have added this code in OnClickListener of previous button
FragmentManager fm = getActivity().getSupportFragmentManager();
if(fm.getBackStackEntryCount()!=0){
fm.popBackStack();
}
Solution of my second question:
use method setArguments() to set the values and getArguments() to get the values
I have MainActivity and SecondActivity. in main activity implemented a viewpager and in my SecondActivity i have button. when i click on button in SecondActivity
move to main activity and jump to spacific viewpager page.
Please provide suitable examples.
In your code on button click write this line,
startActivity(new Intent(CurrentActivity Name, TargetActivity.class).putExtras(tempBundle)
tempBundle is a Bundle argument for identify which position of the pager you want to display at current.
Then in your target Activity get the Bundle information, and set your ViewPager.
viewPager.setCurrentItem(0); //You can set your Bundle information 0 or 1 or 3
That time your ViewPager can set according to given position.
We have Two ways
Use Static Methods OR
Use interface to communicate between activities and fragments also
Communication through Interface
i need an approach how to handle this topic:
i have create a Mainactivity (A) and a Tabbed Activity (B) that contains 3 Tabs (Fragment One, Fragment Two and Fragment Tree)
how to send a string from the Mainactivity to the Fragment One without starting the Tabbed Activity.
when i use bundle
let say: in MainActivity
Bundle bundle=new Bundle();
bundle.putString("key", editText.getText().toString());
BlankFragmentTab1 fragment = new BlankFragmentTab1();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.frag,fragment).commit();
and inside Fragment One i get the String with getarguments.getString("key")
i get a nullpointerexception.
the approach works only by the communication between the Fragments and its container Activity.
thank you very much for your help
LieForBananas is correct.
You can not interact with your FragmentOne without calling its host activity.
However you can use SharedPreferences instead of Bundle for retrieving data.
I have a fragment to which I pass data through a bundle. It does some processes and sends to other fragments. After that there is 2nd set of data has to be sent back to the first fragment. How can this be done?
The following code gives the error:
"IllegalStateException: Fragment already active at android.app.Fragment.setArguments(Fragment.java:696)". So there is a problem in the way the bundle is recreated. What is the correct method to do this?
Code in the activity: It passes two rows of two nested arraylists to fragments and starts the first fragment.
private void changeExercise(int x){
if(x < list.size()) {
Bundle bundle = new Bundle();
bundle.putStringArrayList("ex_list", list.get(x));
bundle.putStringArrayList("ex_data", exercise_data.get(x));
//All fragments use the same data passed from activity using the bundle
preExerciseFragment.setArguments(bundle);
//1st fragment used if !exercise_data.get(x).get(2).equals("bbb") after replacing previous
exerciseFragment.setArguments(bundle);// 2nd fragment used after replacing previous
postExerciseFragment.setArguments(bundle);//3rd fragment used after replacing previous
feedbackFragment.setArguments(bundle); //Then 4th fragment used after replacing previous
if (!exercise_data.get(x).get(2).equals("bbb")) {
getFragmentManager().beginTransaction().add(R.id.workout_layout, preExerciseFragment, "preexercise").commit();
} else {
getFragmentManager().beginTransaction().add(R.id.workout_layout, exerciseFragment, "exercise").commit();
}
} else {
Toast.makeText(this, "Workout is over for the day!! Good job!", Toast.LENGTH_SHORT).show();
}
}
Code in 4th fragment (FeedbackFragment) through an interface:
//
ex_num++;
//
changeExercise(ex_num);
This calls the changeExercise method in the activity. Now the next two rows of the two arraylists in the activity should be passed to the fragment through the bundle. This setArguments method is giving an error.
you don't need to pass data between fragments as a bundle (if they are both active at the same time).
have setters in both fragments that can assign an instance of each other (you can make these interfaces if you want) and then have preExerciseFragment.setPost(postExerciseFragment) and postxerciseFragment.setPre(preExerciseFragment); where you 'setArguments'.
Then both fragments can talk directly through method passes, no need to pack&pass data back and forth inside a bundle.
This is: less code, cleaner, and more efficient since you don't have to create extra bundle objects
So I am trying to get some experience with Fragments, but I'm finding some roadblocks.
My current situation is as follows.
I have an activity that displays a List whose content is determined by Extra Intent parameters sent from the 'calling' activity.
This List activity uses ListFragment declared in the XML like so:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#color/black">
<fragment class="com.pixlworks.NLC.DirectoryBrowse$ListingFragment"
android:id="#+id/listing"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Currently I get the parameter that indicates the type of content directly in the Fragment by accessing the Extra data of the Activity Intent (or saved Bundle if available):
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null)
mListingType = savedInstanceState.getString(Utils.DIRECTORY_TYPE_STORE_KEY);
else
mListingType = getActivity().getIntent().getStringExtra(Utils.DIRECTORY_TYPE_STORE_KEY);
// get content by type, create and set the adapter
}
Now part of my problem is that I am not sure this is the right way to 'pass' that parameter from the Activity to the Fragment.
On top of that, I am getting issues with this setup when using the Action Bar's UP Navigation. When I click on an item in this List Activity it goes to another activity showing the details of the selected item. From this detail activity:
If I use the back button, the List Activity is brought back from the stack as usual and everything works fine.
If I use the ActionBar's UP (despite following steps here), it would seem that a new instance is created instead of using the one in the stack and this new instance obviously is not getting the Extra parameter in the Intent. Since I am expecting the value to exist in the saved Bundle or in the Intent, my app crashes in this situation.
So to boil things down, I am not sure which of these to follow and how to make them work properly with 'UP' navigation:
A) Hold the 'type' parameter in a field in the Activity and save it in the Activity's Bundle onSaveInstanceState. In which case I am not sure how to then pass the value to the Fragment. In this case I would just need to make sure that UP calls the existing instance of the Activity List
B) Continue with my current setup of saving the value in the Fragment instead of the Activity, but again, how to handle the UP navigation correctly?
I know it is kind of multiple things I am asking here at the same time, but they are all connected, so I hope that I can get some help on this.
Thanks for any help in advance!
The UP navigation makes more sense to be used within the same activity level. That is the intention of the codes that you followed in the developers page. Because you started a new activity, if you want to return to previous activity like the back button you will need to call finish() to destroy the details activity first.
As for passing data from activity to fragment, when you create a new instance of fragment, you can pass the data to it as bundle, for example:
// in fragment class
public static MyFragment newInstance(Bundle arg) {
MyFragment f = new MyFragment();
f.setArguments(arg);
return f;
}
When you create a new fragment, you can call:
// in activity
Bundle arg = new Bundle();
int info = ...;
arg.putInt("INFO",info);
...
MyFragment mFragment = MyFragment.newInstance(arg);
Finally, to get the data in fragment:
int info = getArguments().getInt("INFO");
...
Instead of directly calling MyFragment mFragment = new MyFragment() to instantiate the fragment, you should use a static method to instantiate it. This is to prevent some crashes which might happen if you rotate the screen and the framework complains that it couldn't find a public empty constructor.
UPDATE
To answer your questions:
1) Say you start from activity A -> activity B. Then in activity B you press the up button. By logic of use, the up button will not bring you back to activity A, because its intention is to navigate one level up,but still inside, activity B. To return to activity A, you need to call finish() to destroy activity B first.
2) If your fragment is created in xml, you still can set arguments. In your xml, you set an id for the fragment android:id="#+id/fragment_id", then
// in activity
FragmentManager fm = getSupportFragmentManager(); // or getFragmentManager() if you don't have backward compatibility
MyFragment mFragment = fm.findFragmentById(R.id.fragment_id);
Bundle arg = new Bundle();
// put data blah blah
mFragment.setArguments(arg);
Just make sure you set the arguments before you use the fragment.
Simply said, intent is used when you pass data between calling activities; bundle is used when you want to pass data from activity to fragment.