Send data to fragment from Activity - android

I have Main Activity with View Pager inside that activity. So, I have also FragmentStatePager adapter for handling which fragment is display inside ViewPager.
Anyway, as you know ViewPager loads previous, current and next fragment in memory and that's problem because I want to change content values in next fragment from current fragment based on user interaction from current fragment.
public class StageOneActivity extends FragmentActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_stage_one);
//ViewPager for Introduction
mStageOnePager = (ViewPager) findViewById(R.id.vp_stage_one);
mStageOnePager.setAdapter(new IntroFragmentPagerAdapter(getSupportFragmentManager()));
mStageOnePager.setOffscreenPageLimit(1);
//mStageOnePager.setCurrentItem(8);
}
private class IntroFragmentPagerAdapter extends FragmentStatePagerAdapter {
public IntroFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_01);
case 1:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_02);
case 2:
return TitleSpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_03, R.drawable.bkg_page_1_50);
case 3:
return CurrencySpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_03, R.drawable.pack_of_20);
case 4:
return SimpleSpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_05, R.drawable.bkg_page_1_50);
case 5:
return MoneySpentFragment.newInstance(getResources().getColor(R.color.green), R.drawable.money_spent_1, R.drawable.money_spent_2, "0");
case 6:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_07);
How I can send data to fragment who is already loaded and content is added in ViewPager?
I decided to try to use ViewPager.setOnPageChangeListener and detected when user scrolled to selected screen, but problem is how I can send that data to that Fragment and show it?

You can use eventbus:
https://github.com/greenrobot/EventBus
It's easy to setup and use.
HOWTO with example and code snippets:
https://github.com/greenrobot/EventBus/blob/master/HOWTO.md

You need to define an interface in the fragment and implement it within the Activity.Google documentation:
http://developer.android.com/training/basics/fragments/communicating.html
In your class it'd be something like this:
public Fragment StageOneFragment{
public interface itf{
}
...
}
public class StageOneActivity extends FragmentActivity implements StageOneFragment.itf{
...
}
Hope it helps, you should be able to implement the interface that way.

Related

I've got a weird bug when using a ViewPager inside a Fragment

Okay i'll try and make this as clear as possible. I have a Fragment called CheckerManager which contains a ViewPager. This ViewPager will allow the user to swipe between 3 Fragments all of which are an instance of another Fragment called CheckerFragment. I'm using a FragmentPagerAdapter to handle paging. Here's how it looks
private class PagerAdapter extends FragmentPagerAdapter {
CharSequence mTabTitles[];
public PagerAdapter(FragmentManager fm, CharSequence tabTitles[]) {
super(fm);
mTabTitles = tabTitles;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return CheckerFragment.newInstance(MainFragment.DRAW_TITLE_LOTTO);
case 1:
return CheckerFragment.newInstance(MainFragment.DRAW_TITLE_DAILY);
case 2:
return CheckerFragment.newInstance(MainFragment.DRAW_TITLE_EURO);
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
return mTabTitles[position];
}
#Override
public int getCount() {
return 3;
}
}
I know that the ViewPager will always create the Fragment either side of the current Fragment. So say my 3 CheckerFragments are called A, B and C and the current Fragment is A. B has already been created. But my problem is that even though I am still looking at Fragment A, Fragment B is the 'active' Fragment. Every input I make is actually corresponding to Fragment B and not A. The active Fragment is always the one which has been created last by the ViewPager.
I've looked at quite a few things to see if anyone has had the same problem but i'm finding it difficult to even describe what's wrong. I think it's something to with the fact that all of the ViewPagers fragments are of the same type ie - CheckerFragment. I have a working implementation of a ViewPager inside a fragment elsewhere in the application and the only difference I can tell is that each page is a different type of Fragment.
Any help would be appreciated!
*EDIT
PagerAdapter adapter = new PagerAdapter(getChildFragmentManager(), tabTitles);
ViewPager viewPager = (ViewPager)view.findViewById(R.id.viewPagerChecker);
viewPager.setAdapter(adapter);
I feel pretty stupid but I found out what the issue was. In my CheckerFragment I would call getArguments() to retrieve a String extra and I would use this to determine how to layout the fragment. Problem was I made this extra a static member of CheckerFragment. So every time a new Fragment was created it was using the most recent extra.
Moral of the story - Don't make your fragments extra a static member if you plan on making multiple instances of that fragment.

Passing data between fragments contained in an activity

I have an activity A with 3 fragments. Each fragments replaces each other, hence at a given time only 1 is visible.
HomeFragment has 2 textviews wrapped inside 2 cardviews. Each cardview represents a text value which comes from Fragment1 and Fragment2. When I click on say Card1,I get to the Fragment1.
Fragment1 has some cardviews, when I selects any of them I navigate back to HomeFragment and update the cardview text based on my selection in Fragment1.Here is the switch statement, depending upon what card user selects I put that in a bundle and pass it to HomeFragment.
switch (v.getId()) {
case R.id.card_view0:
Fragment1Bundle.putString("Test", "Testing");
bundle.putBundle("Fragment1Bundle", Fragment1Bundle);
fragmentTransaction.setCustomAnimations(R.anim.slideup, R.anim.slidedown, R.anim.slideup, R.anim.slidedown);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
Fragment2 has same behavior as Fragment 1.
switch (v.getId()) {
case R.id.card_view0:
Fragment2Bundle.putString("Test2", "Tetsing");
bundle.putBundle("Fragment2Bundle", Fragment2Bundle);
fragmentTransaction.setCustomAnimations(R.anim.slideup, R.anim.slidedown, R.anim.slideup, R.anim.slidedown);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
My challenge is that I am using bundles to pass data between fragments, My home fragment gets updated with the data it from fragment1 but when I go to fragment 2 and after making the selection come back to Home fragment, my fragment1 data is set to default. This is what I am doing in Home Fragments onCreateView()
try {
bundle1 = getArguments().getBundle("Fragment1Bundle");
bundle2 = getArguments().getBundle("Fragment2Bundle");
tv.setText(bundle1.getString("Test") == null ? null : bundle1.getString("Test"));
tv2.setText(bundle2.getString("Test2") == null ? nul : bundle2.getString("Test2"));
} catch (NullPointerException e) {
Log.d(TAG, e.printStackTrace());
}
I know that I am creating a new Homefragment in my fragment transaction in both fragment1 and fragment2, How can I keep just 1 instance of Home fragment around.
Another design recommended by Google is to use the main Activity and 2 fragments (in your case Fragment1 and Fragment2). I can see your problem of passing data bundle to HomeFragment. This suggested design uses MainActivity which is declared static (may be required for scoping issue). And it uses an interface to be established between Activity and a Fragment. I think the interface is easier than passing bundle back to the HomeFragment.
A Google webpage is # Communicating with Other Fragments. This is not just my opinion. A good SO link, I think, is How to pass data between fragments.
Code snippet from the webpage...
An example of Fragment to Activity communication:
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
...
An example of Activity to Fragment communication:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
}
}
Note:
OnHeadlineSelectedListener is the interface created by the Fragment.
The created method onArticleSelected has a parameter position, which comes from the ListView in ListFragment (in the sample).
You can still set data bundles and send data between Activity and Fragment. However I have not sent back data from Fragment to Activity. I normally use Fragment to handle much of UI updates.
how to pass values from activity to already open fragment and update array-list help me please. when I using interface the array-list size is zero what I do? do not us bundle method.
public class Main2Activity extends AppCompatActivity{
String desc = "data";
OnDataPassedListener onDataPassedListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
String passedArg = getIntent().getExtras().getString("id");
Log.d("data",passedArg);
Scription scription = new Scription();
onDataPassedListener = (OnDataPassedListener)scription;
onDataPassedListener.onDataPassed(passedArg,desc);
}
public interface OnDataPassedListener {
void onDataPassed(String text,String name);
}
}
public class Test extends Fragment implements
Main2Activity.OnDataPassedListener{
.
.
.
.
#Override
public void onDataPassed(String text,String name) {
monthlylists.get(Integer.valueOf(text)).setFood_type(name);
}

Tabs with ViewPager - How to get instance and not new object?

I am using the standard Android tabs and I need to access my tabs from the parent activity.
I do the following in my MainActivity to get my tabs:
myTab = ((FirstTabFragment)mAdapter.getItem(index));
The problem is that I always get a new object and not the instance because the getItem is implemented as follows:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Status fragment activity
return new FirstTabFragment();
case 1:
// Mission fragment activity
return new SecondTabFragment();
case 2:
// Team fragment activity
return new ThirdTabFragment();
}
return null;
}
...
I googled quite a lot but I still can't find any working solution to get the instance ob my Fragments.
I need the instance because I need to alter the fragment's views and therefore I need it's variables.
Any ideas?
Thanks!
The best way is to use the FragmentManager with the method findFragmentById or findFragmentByTag. Of course, you need to declare an ID or a TAG for each fragment created by the FragmentPagerAdapter. If I remember correctly, the default implementation uses the class name as tag.
Save the fragment in SparseArray or in HashMap. Add the fragment in array in your getItem method also override the onFragmentDestroy method. In method remove the item from SparseArray or HashMap. Now create a getter method somthing like this
public Fragment getFragment(int pos) {
return array.get(pos);
}

Split activity into multiple files

I'm writing an android application, which has one activity, which contains several fragments. Now I want to know is there a way to split that activity into several files - to have separate file for each fragment?
For making my question clearer here is structure of my activity
public class MainActivity extends Activity implements ActionBar.TabListener
{
#Override
public Fragment getItem(int position) {
switch(position)
{
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
case 3:
return new Fragment4();
}
}
public static class Fragment1 extends Fragment {}
public static class Fragment2 extends Fragment {}
public static class Fragment3 extends Fragment {}
public static class Fragment4 extends Fragment {}
}
Thank you in advance!
Now I want to know is there a way to split that activity into several files - to have separate file for each fragment
If the above means that you recently got all your Fragments as inner classes within your Activity class, then answer is yes - just create separate java class file for each fragment.

Viewpager pages with different layouts but same fragment class

Using a ViewPager, I'm working on a guide that tells the user how to use my app.
This is how i currently add/setup the pages:
...
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Guide_fragment();
case 1:
return new Guide_fragment_2();
case 2,3,4 etc.
default:
return null;
}
}
...
But this way I have to have a fragment class for each page, and since the pages are only images and text, I figured that it might not be necessary.
Is there a way I can just use the same fragment class for all pages and then just assign a different layouts to it?
Thanks
Is there a way I can just use the same fragment class for all pages and then just assign a different layouts to it?
Sure. Pass data into the fragment indicating what to display, typically via the factory pattern:
Create a static newInstance() method that takes the data you might ordinarily pass to the fragment constructor
newInstance() takes those parameters, puts them in a Bundle, and attaches the Bundle to a newly-constructed instance of your fragment via setArguments()
Your fragment, when it needs this data, calls getArguments() to retrieve the Bundle
This ensures that your data will survive configuration changes.

Categories

Resources