How to pass data from an Activity to Tab Fragments using ViewPager? - android

Hey StackOverFlow community ! I really need help.. :(
I'm searching for 2 or 3 hours now and didn't find anything that is relevant and simple.
I explain the context :
I have an Activity A1. This activity contains 3 fragments F1, F2, F3. It uses a ViewPager so the 3 fragments are in facts selected either by selecting a tab or by swiping the screen and this works.
What I want to do now :
For some reasons, I call a Web Service for data in the activity. The data is dependent on the intent that the activity A1 gets from the original calling activity A0 (It's a group_id). So, I want to send this data that I get in A1 from the Web Service to each of my fragments F1, F2 and F3.
Do you have a solution or an explanation of how the to pass data to fragments in ViewPager ?
Thanks a lot!
There is the base code of my Activity A1 :
public class ShowGroupActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Infos", "Parcours", "Mur" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.activity_show_group);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
Here is an example of a fragment : F1 (In which I want to display some data given by A1).
public class GroupInfoFragment extends Fragment {
public GroupInfoFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_group_info, container, false);
return v;
}
}

The easiest and fastest way to do it is by using EventBus.
Just post an event at your onResponse method in the activity and the fragment will handle the rest.
Activity-
Create a NetworkResponceEvent class
OnResponse called: post a new NetworkResponceEvent to the eventbus.
Fragment-
Register- onResume
UnRegister- osPause
Create method onEvent(NetworkResponceEvent e)- handle all of the
updates here.

You should use the getActivity() method from your fragments.
I would recommend declaring an interface inside your fragment, like this:
public class GroupInfoFragment extends Fragment {
...
public interface Callbacks {
// you should declare methods for returning the data you want form your activity here
Foo getData();
}
...
}
And then implementing this interface in your ShowGroupActivity class, like this:
public class ShowGroupActivity extends FragmentActivity implements
ActionBar.TabListener, GroupInfoFragment.Callbacks {
...
#Override
Foo getData() {
return mData;
}
...
}
Then you would be able to get the data you want from your fragment classes by calling:
GroupInfoFragment.Callbacks callbacks = (GroupInfoFragment.Callbacks) getActivity();
Foo data = callbacks.getData;
By doing this, you can implement your fragment class without worrying about the activity implementation.
Additional Notes
You can also override your fragment's onAttach() method so you can always guarantee that your fragment is being attached to an activity that implements the Callback interface. You can also keep a reference to the Callback instance:
Callbacks mCallbacks;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof Callbacks)) {
throw new ClassCastException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}

Related

How to call fragment method from activity

I'm populating fragments in a tablayout. I have a method in one of my fragments, and i want to call it from an activity. But when i tried to have reference of the fragment by doing like this Fragment myFragment = (Fragment ) getSupportFragmentManager().findFragmentById(R.id.my_fragment), myFragment is null. I'm new to android. (Sorry for the bad english)
My code so far.
public class DashboardActivity extends AppCompatActivity {
private ViewPager pager;
private TabLayout tabLayout;
private Toolbar dashboardToolbar;
public static int position;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard_activity);
HomeFragment myFragment = new HomeFragment ();
if(getSupportFragmentManager().findFragmentById(R.id.homeFragment) == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.homeFragment, myFragment).commit();
}
pager = (ViewPager) findViewById(R.id.view_pager);
setupViewPager(pager);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager);
pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// Toast.makeText(DashboardActivity.this, "tabSelected: " + tab.getText()+" "+ tab.getPosition(), Toast.LENGTH_SHORT).show();
// no where in the code it is defined what will happen when tab is tapped/selected by the user
// this is why the following line is necessary
// we need to manually set the correct fragment when a tab is selected/tapped
// and this is the problem in your code
pager.setCurrentItem(tab.getPosition());
position = tab.getPosition();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
// Toast.makeText(DashboardActivity.this, "tabReSelected: " + tab.getText(), Toast.LENGTH_SHORT).show();
position = tab.getPosition();
// Reload your recyclerView here
}
});
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new HomeFragment(), "FOR YOU");
adapter.addFragment(new NotificationFragment(), "NOTIF");
adapter.addFragment(new ChatFragment(), "CHAT");
adapter.addFragment(new ProfileFragment(), "PROFILE");
viewPager.setAdapter(adapter);
}
}
Fragment
public class HomeFragment extends Fragment {
// Objects Declaration
public HomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.homeFragment, container, false);
}
public void myMethod(){ //method to be called
//do something
}
}
Activity
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_filter);
HomeFragment myFragment= (HomeFragment ) getSupportFragmentManager().findFragmentById(R.id.homeFragment);
if(myFragment!= null) {
Toast.makeText(ActivityFilter.this, "Not null.", Toast.LENGTH_SHORT).show();
home.myMethod(); // this line is not accessed since myFragment is null
}else{
Toast.makeText(ActivityFilter.this, "Null fragment.", Toast.LENGTH_SHORT).show();
}
}
}
You should use a Callback.
Create a public interface in your fragment.
public interface iCommunicateListener{
void communicate(String msg);
}
You also have to make the activity your listener.
(You can have many listeners, but fragments are supposed to be reusable, so if you have many listeners it will not be as reusable as it could and should be)
private iCommunicateListener listener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
listener = (iCommunicateListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement iCommunicateListener");
}
}
Now you have active listener.
In your onClicks or whenever you want send information to your activity, you have to call listener.communicate("doSomething");
Your Activity must implement the iCommunicateListener.
After implementation of the method communicate you can choose your logic for the different Strings or whatever you want to send through the callback.
There are many other ways for communication between Activities and Fragments, but since you are just beggining learn this one. After you implement it and you see the result you can take a look at this library which will definately help you in your android development. EventBus
With EventBus you will not have to use the callbacks which will make your fragments even more reusable and flexible, but first learn the normal Callbacks. It is a basic pattern and you will use it in many different situations.
More on Fragments: Fragments
Hope this helps!

keep previously loaded fragment instance when tab changes instead of creating new one in android

I have a tab swiped layout which includes four tabs each of which have their own layout and fragment, in my main activity layout a viewpager takes part for changing tabs. specific view(tab) loads when app starts up and the others will be loaded when the tab changes. my problem is when I nevigate to the third or forth tab (not the second tab) a new instance of it's corresponding fragment will be created instead of loading previously created fragment (the expected behavior that only occur for the second tab).When I navigate to the second tab (SecondPageFragment()) and again come back to first tab it works correct and doesn't create a new IndexFragment, it load the previously created fragment instead so every thing is fine in this case but when I go to the third or forth tab and then come back to first tab it creates an new instance of IndexFragment.
what's the possible reason for that and why it only happens for third,forth etc tab and only second tab works correct and as expected ????
here is my codes that switch the tabs and their corresponding fragments
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new ForthPageFragment();
case 1:
return new ThirdPageFragment();
case 2:
return new SecondPageFragment();
case 3:
return new IndexFragment();
default :
break;
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 4;
}
}
and here is my main activity code :
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "صفحه چهارم","صفحه سوم","صفحه دوم","صفحه اصلی" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager)findViewById(R.id.tabpager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
viewPager.setCurrentItem(3);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
}
viewPager.setOffscreenPageLimit(3);

Load listview items in fragment from main activity

I am a newbie in android programming.I added three fragments in my main activity as follows.Each fragment contains a list view.The items in list view is added from json output.Now i need to call same json request from each fragments.Can i set listview items from my main activity ? and avoid 2 json requests ?
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends ActionBarActivity implements
android.support.v7.app.ActionBar.TabListener {
ViewPager viewPager;
// Using appcompat action bar
private android.support.v7.app.ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
FragmentManager fragmnetManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmnetManager));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageSelected(int pos)
{
actionBar.setSelectedNavigationItem(pos);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
// Getting actionbar
actionBar = getSupportActionBar();
// Setting navigation mode to actionbar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Now adding a new tab to action bar and setting title, icon and
// implementing listener
android.support.v7.app.ActionBar.Tab tab1 = actionBar.newTab();
tab1.setText("TAB1");
// tab1.setIcon(R.drawable.ic_launcher);
tab1.setTabListener(this);
android.support.v7.app.ActionBar.Tab tab2 = actionBar.newTab();
tab2.setText("TAB2");
tab2.setTabListener(this);
android.support.v7.app.ActionBar.Tab tab3 = actionBar.newTab();
tab3.setText("TAB3");
tab3.setTabListener(this);
// Now finally adding all tabs to actionbar
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
#Override
public void onTabReselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1)
{
}
#Override
public void onTabSelected(android.support.v7.app.ActionBar.Tab tab,
FragmentTransaction arg1)
{
// Setting current position of tab to view pager
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1) {
}
}
// My adapter i.e. custom adapter for displaying fragments over view pager
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
// Getting fragments according to selected position
Fragment fragment = null;
if (i == 0) {
fragment = new FragmentA();
}
if (i == 1) {
fragment = new FragmentB();
}
if (i == 2) {
fragment = new FragmentC();
}
// and finally returning fragments
return fragment;
}
#Override
public int getCount() {
// Returning no. of counts of fragments
return 3;
}
}
You can also try this if you don't want to implement interface (because you are having only three fragment) - To avoid two json request on different fragment, just send one json request and after getting data in two different list, you can call a method in second fragment to set listview's data in second fragment from first fragment.
Let's say you got two list(firstList, secondList) of data from jsonResponse then set first arraylist in currentFragment and to set data in second fragment try like below method-
Define fragment's instances in Activity like -
FirstFragment firstFragment;
SecondFragment secondFragment;
initialize them where you add fragment like -
secondFragment = new SecondFragment();
in SecondFragment -
public void updateListView(ArrayList list){
secondArrayList.addAll(list);
secondAdapter = new Adapter(superContext, R.layout.single_item, secondArrayList);
listView.setAdapter(secondAdapter);
}
call this method from activity -
secondFragment.updateListView(secondList);
This solution is better if you have number of fragments small.
Yes you can. Create a interface in your mainActivity as follows
public interface Communicator{
void onDataLoaded(<Whatever data you want to send to fragment>)
}
now create an instance of this interface in your main activity
Communicator mCommunicator;
In your getItem method, for which fragment you want to send data to initialize the communicator as follows
mCommunicator=(Communicator)fragment;
Then in your main activity once your JSON is loaded just call mCommunicator.onDataLoaded();
Make sure your fragment implements this interface. Once you implement it you will get data there and you can update your listview.

Call Activity which extends FragmentActivity using Fragment in android

I have Activity for tabLayout using ViewPager.
Code :
public class Home extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "Instant Opportunity", "Events", "Experts" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
And another activity for Slider, code is as below :
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new Home();
break;
case 1:
fragment = new Gallery();
break;
default:
break;
}
Now, here at case 0: I want to call that Home activity. But It is showing error. How to call this ?
When I take cursor on new Home(), It says can't convert from Home to Fragment.
You can use a ViewPager inside a Fragment. You have to use inner fragments with the nested fragments method, as you can read on the Documentation:
You can now embed fragments inside fragments. This is useful for a variety of situations in which you want to place dynamic and re-usable UI components into a UI component that is itself dynamic and re-usable. For example, if you use ViewPager to create fragments that swipe left and right and consume a majority of the screen space, you can now insert fragments into each fragment page.
You need to change Home as extends Fragment and use getChildFragmentManager() method for your adapter. There are some revelant posts on this kind of behaviour:
ViewPager inside ViewPager
How set ViewPager inside a Fragment
Display fragment viewpager within a fragment
How to add a Fragment inside a ViewPager using Nested Fragment (Android 4.2)
Hope this helps.

How to manage some items of a fragment in another class from an ActionBarActivity, Android

First off, you have to forgive me, because my English is very bad.
I'll try to explain the issue:
I have an ActionBarActivity with two pages (ViewPager).
Every page has a Fragment.
My problem is: how to use the elements of each Fragment from this ActionBarActivity?
My code is this:
ActionBarActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manage_devices);
mActionbar = getSupportActionBar();
mActionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mPager = (ViewPager) findViewById(R.id.pager);
FragmentManager fm = getSupportFragmentManager();
MyFragmentPagerAdapter fragmentPagerAdapter = new MyFragmentPagerAdapter(fm);
mPager.setAdapter(fragmentPagerAdapter);
mActionbar.setDisplayShowTitleEnabled(true);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mPager.setCurrentItem(tab.getPosition());}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
};
mActionbar.addTab(mActionbar.newTab().setText("SENSORS").setTabListener(tabListener));
mActionbar.addTab(mActionbar.newTab().setText("SIGNALS").setTabListener(tabListener));
/** Defining a listener for pageChange */
ViewPager.SimpleOnPageChangeListener pageChangeListener = new ViewPager.SimpleOnPageChangeListener(){
**#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if(position == 0 & !hecho){
currView = mPager.getChildAt(mPager.getCurrentItem());
DevicesListView = (ListView) currView.findViewById(R.id.DevicesListView);
DevicesListView.setAdapter(DevicesAdapter);
DevicesListView.setOnItemClickListener(DeviceOnItemClickListener);
hecho = true;}
else if(!hecho){
mGraph = (GraphView)findViewById(R.id.graph);
}
mActionbar.setSelectedNavigationItem(position);
}**
};
/** Setting the pageChange listener to the viewPager */
mPager.setOnPageChangeListener(pageChangeListener);
}
To get a Listview, I access it in OnPageSelected.
But this is bad for me, because I need to change a page for getting the Listview and build it.
ManageFragment.java
public class ManageFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("","Entra");
return inflater.inflate(R.layout.manage_fragment, null);
}
}
My Listview is in the manage_fragment layout.
This can help: Illustration
Thank you very much!!!
If your fragment already created you can just use findViewById() in your activity and just find the view you want.
So you should inform your activity that the fragment view already created through an interface for example:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnViewCreatedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
And then call the interface after Fragment's onCreateView.

Categories

Resources