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.
Related
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);
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;
}
I am developing an app which is using ActionBar.NAVIGATION_MODE_TABS and a separate FragmentPagerAdapter class in order to swipe through 5 different screens. On these screens there are buttons you can press to load a new activity, and then go back to the MainActivity when done. My problem is, every time you go back and reload the MainActivity it defaults back to the first tab (0).
I have tried many different solutions to try and get the previously selected tab to load when the activity is reloaded including SharedPreferences, saving instance state and trying to force the FragmentPagerAdapter class to load a certain fragment when called - but something keeps overriding it and it always goes back to the first tab (0) without fail. I would be really grateful for any possible solutions to this.
Code as follows:
public class MainActivity extends FragmentActivity implements TabListener {
ActionBar tabBar;
ViewPager viewPager;
#Override
protected void onCreate(Bundle currenttab) {
super.onCreate(currenttab);
setContentView(R.layout.activity_main);
// Sets up view pager
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setCurrentItem(0);
viewPager.setAdapter(new MainAdapter(getSupportFragmentManager()));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int currenttab) {
tabBar.setSelectedNavigationItem(currenttab);
}
#Override
public void onPageScrolled(int currenttab, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int currenttab) {
}
});
// Adds tabs to action bar
tabBar = getActionBar();
tabBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = tabBar.newTab();
tab1.setIcon(R.drawable.action);
tab1.setTabListener(this);
ActionBar.Tab tab2 = tabBar.newTab();
tab2.setIcon(R.drawable.jobs);
tab2.setTabListener(this);
ActionBar.Tab tab3 = tabBar.newTab();
tab3.setIcon(R.drawable.historic);
tab3.setTabListener(this);
ActionBar.Tab tab4 = tabBar.newTab();
tab4.setIcon(R.drawable.breeds);
tab4.setTabListener(this);
ActionBar.Tab tab5 = tabBar.newTab();
tab5.setIcon(R.drawable.special);
tab5.setTabListener(this);
tabBar.addTab(tab1);
tabBar.addTab(tab2);
tabBar.addTab(tab3);
tabBar.addTab(tab4);
tabBar.addTab(tab5);
}
// Action bar methods
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
// Class to deal with swipe function
class MainAdapter extends FragmentPagerAdapter {
public MainAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int currenttab) {
// TODO Auto-generated method stub
Fragment fragment = null;
if (currenttab == 0) {
fragment = new FragmentAction();
}
if (currenttab == 1) {
fragment = new FragmentJobs();
}
if (currenttab == 2) {
fragment = new FragmentHistory();
}
if (currenttab == 3) {
fragment = new FragmentBreeds();
}
if (currenttab == 4) {
fragment = new FragmentSpecial();
}
return fragment;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return 5;
}
}
I managed to resolve this by making my back buttons behavior mimic the built in behavior of calling onBackPressed();. The problem was going back using my previous code was creating a new instance of my MainActivity thus defaulting it to the first tab.
I have 3 fragments... with their 3 navigation tabs.
The problem is that if i'm on the first tab, and i click the third.. when I click another time the first, it reloads all the fragment. If I click the second tab (in the middle) and I click the first, it doesn't reload.
My objective is that I don't want to refresh my fragments never!
How can I do it?
My code is:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
// Return Items
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Retos();
case 1:
return new Amics();
case 2:
return new Ranking();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
And this :
public class Perfil extends ActionBarActivity implements ActionBar.TabListener{
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private SearchView mSearchView;
private TextView mStatusView;
// Tab titles
private String[] tabs = { "TAB1", "TAB2", "TAB3" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.perfil);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
/** Creating fragment1 Tab */
Tab tab = actionBar.newTab()
.setText("TAB1")
.setTabListener(this);
actionBar.addTab(tab);
/** Creating fragment2 Tab */
tab = actionBar.newTab()
.setText("TAB2")
.setTabListener(this);
//.setIcon(R.drawable.ic_action_group);
actionBar.addTab(tab);
/** Creating fragment3 Tab */
tab = actionBar.newTab()
.setText("TAB3")
.setTabListener(this);
actionBar.addTab(tab);
/**
* on swiping the viewpager make respective tab selected
* */
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) {
}
}
viewPager.setOffscreenPageLimit(C_FRAGMENTS_TO_KEEP_IN_MEMORY);
C_FRAGMENTS_TO_KEEP_IN_MEMORY is the number of tabs at right and left of the current selected tab to keep in memory. So in your case should be 2.
Please be sure that you are NOT creating a new fragment instance each time you call the getItem method in you viewpager adapter.
Check the #Rarw answer in this page.
Try setting your ViewPager offScreenPageLimit to cover the number of fragments you are trying to load. OffScreenPageLimist keeps fragments alive in an idle state when they are not visible. I don't see that value set in your code and based on what you're describing, that fragments keep recycling, it sounds to me like you're using the default state of 1, which will only retain one of the fragments off screen and not both.
Some caveats, this approach only really works if you know in advance how many fragments you will need since if you're dynamically adding and removing fragments its hard to know how many if any to retain.
UPDATE
This is likely why you're pages are refreshing:
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Retos();
case 1:
return new Amics();
case 2:
return new Ranking();
}
return null;
}
You keep returning a new fragment each time you switch id. What you should do something like this:
case 0:
if(mRetrosFragment == null)
mRetrosFragment = new Retros();
return mRetrosFragment;
This way you stop recreating the fragment every time the tab changes and instead retain that instance.
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.