conflict between fragments inside a viewpager - android

whenever i swipe to move to the next fragment the code inside another fragment gets executed tho the layout is loaded properly and the code also but it also executes the code of another fragment
ex: 3 fragments A,b,c
when i swipe from fragment A to fragment b : fragment b layout and code are executed but also fragment c code
when i swipe from b to c , only the code and layout of fragment c ,so its executed properly
so the problem is if it isnt the last fragment it calls the code of next one
here is my main_activty code
public class Main2Activity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
home h1 = new home();
return h1;
case 1:
status st = new status();
return st;
case 2:
info info = new info();
return info;
case 3:
setting set = new setting();
return set;
}
return null;
}
#Override
public int getCount() {
return 4;
}
}
}

Your SectionsPagerAdapter is extending FragmentStatePagerAdapter, and its default behaviour is to preload at least one page for optimisation reasons. You can set the number of fragments it preloads using setOffscreenPageLimit but it has to be at least one.
You can use this method in your fragment and put in there something that you want executed only once the fragment becomes visible:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
}
}

Related

Launching new Fragment Inside ViewPager

I'm on the verge of losing it. Anyone that could help me solve this issue will be showered with coding props for all of eternity.
I have a Tablayout containing 3 Tabs within my Main Activity. Each tab contains their own Fragment(Tasks,Calendar,Contacts). There is a FAB button in the Main Activity that lives on top of all the Fragments and performs a certain action base on what Tab I'm currently in.
My main issue is that, when I'm in Tab1, and the Fab is clicked, I need to replace the Tasks Fragment with a different Fragment called AddContact.
I've been looking up how to solve this for hours and finally settled on an earlier answer from this stack post
The issue is, I'm not quite grasping how they were able to do it.
My understanding is that the swapping of Fragments should be managed by the getItem method within the View Pager Adapter. And that there should be a listener that exists between the ViewPagerAdapter and the buttonClicked action in my Main Activity that tells it to execute.
The problem is that I can't make this link. I've tried a number of things but with no luck. Below I included my MainActivity Class and my ViewPagerAdapter Class. If someone could please explain to me how I could swap out my Tasks Fragment with my AddContacts Fragment in the ViewPager, I would greatly appreciate it
Main Activity:
public class MainActivity extends AppCompatActivity {
private CollapsingToolbarLayout collapsingToolbarLayout;
private ViewPager viewPager;
private ArrayList<Fragment> fragments = new ArrayList<>();
private ArrayList<String> titles = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
collapsingToolbarLayout = (CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
setSupportActionBar(toolbar);
fragments.addAll(Arrays.asList(new Tasks(),new Calendar(),new Contacts()));
titles.addAll(Arrays.asList(getResources().getString(R.string.fragment_task_title),
getResources().getString(R.string.fragment_cal_title),getResources().getString(R.string.fragment_contacts_title)));
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabs);
final FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
viewPager = (ViewPager)findViewById(R.id.container);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),fragments,titles);
viewPager.setAdapter(viewPagerAdapter);
viewPager.setCurrentItem(1);
tabLayout.setupWithViewPager(viewPager);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fabAction();
}
});
}
public void fabAction(){
int current = viewPager.getCurrentItem();
switch (current){
case 0:{
//Need to indicate Fragment Swap here somehow. Through Listener?
break;
}
}
}}
ViewPagerAdapter Class:
public class ViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments;
ArrayList<String> titles;
private Fragment mFragmentAtPos0;
public ViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, ArrayList<String>titles) {
super(fm);
this.fragments = fragments;
this.titles = titles;
}
#Override
public Fragment getItem(int position) {
if (position == 0)
{
if (mFragmentAtPos0 == null)
{
//HANDLES THE CHANGING OF FRAGMENTS IN HERE USING THE LISTENER BELOW? BUT I'M NOT GRASPING THE LOGIC
//ON HOW TO IMPLEMENT THIS.
}
}
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
//GOT FROM LESSON - ALLOWS VIEWPAGER TO CHANGE IT'S VIEW AND ATTACH NEW FRAGMENT WHEN LAUNCHED
#Override
public int getItemPosition(Object object)
{
if (object instanceof Tasks && mFragmentAtPos0 instanceof AddContact)
return POSITION_NONE;
return POSITION_UNCHANGED;
}
//GOT FROM LESSON. A LISTENER BUT I'M NOT SURE WHERE AND HOW TO IMPLEMENT IT. WHERE IN THE MAIN ACTIVITY SHOULD THIS
//GO? HOW DOES IT COMMUNICATE BACK TO THE ADAPTER?
public interface FirstPageFragmentListener
{
void onSwitchToNextFragment();
}
The post or lesson that Im referring is also from 5 years ago so I don't know if there's a simpler way to implement this, in which case I would love to hear it. Thanks so much.

Fragments display getting reset

I have setup a list of fragments using TabLayout and ViewPager on MainActivity as such
public class MainActivity extends AppCompatActivity implements Fragment1.OnFragmentInteractionListener, Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener, Fragment4.OnFragmentInteractionListener
, Fragment5.OnFragmentInteractionListener{
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new CustomAdapater(getSupportFragmentManager(), getApplicationContext()));
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#51ffff"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
switch (tab.getPosition()) {
case 0:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#ced21f"));
break;
case 1:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#51ffff"));
break;
case 2:
tabLayout.setSelectedTabIndicatorColor(Color.parseColor("#FF0000"));
break;
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
});
}
#Override
public void onFragmentInteraction(Uri uri) {
}
private class CustomAdapater extends FragmentPagerAdapter {
private String fragments[] = {"Control", "Connection", "Log", "Others", "Others2"};
public CustomAdapater(FragmentManager supportFragmentManager, Context applicationContext) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Fragment1();
case 1:
return new Fragment3();
case 2:
return new Fragment2();
case 3:
return new Fragment4();
case 4:
return new Fragment5();
default:
return null;
}
}
#Override
public int getCount() {
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments[position];
}
}
}
Somehow when I transit from Fragment1 to Fragment3 and back to Fragment1, the views on Fragment1 gets reset to original state(Like it was just created).
This only happens if I transit 2 fragment away from the current Fragment. For example 2->4 or 3->1.
Everything is fine if the transition is next to each other, for example 2->3 or 1->2.
This is my first android app so do pardon me.
It seems like it is creating a new fragment instead loading of existing ones
Your fragment get destroyed due to the fact that by default viewpager retain only one fragment at a time while moving around so you can simply use
viewPager.setOffscreenPageLimit(no_of_fragment_to_retain);
or
viewPager.setOffscreenPageLimit(3); // in your case
so when you come back from 4->1 or 3->1 you will get the previous stored state of your fragment. link to docs
First :
viewPager.setAdapter(new CustomAdapater(getSupportFragmentManager(), getBaseContext()));
Now see : in get Item method of View pager evrytime when you go to new tab a new instance of fragment is created So the previous view is lost . You should retain state in your fragment class.
or a simple solution is use FragmentstatepagerAdapter instead of FragmentPagerAdapter in your Adapter class.
Let me know if it helps

I don't want to refresh fragment on change

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.

How to handle AsyncTask's in ActionBarActivity Fragments when ViewPager is used?

I'm using ActionBarActivity to create 5 tabs. I have used ViewPager to swipe between the 5 tabs using SectionsPagerAdapter which extends FragmentPagerAdapter. Each tab has a fragment with an asynctask called in oncreateview method. When I'm in one fragment, asynctask in other fragment is being called.
I tried using toast messages in oncreateview method is each fragment instead of asynctask. But wrong toast messages are being fired in wrong fragment.
Oncreate method code:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager_exp);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
actionBar.setTitle(getHomePageTitle(position));
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
{
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(actionBar.newTab()
.setIcon(getPagedrawable(i))
.setTabListener(this));
}
// Adapter class code:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
Fragment1 f1 = new Fragment1();
return f1;
case 1:
Fragment2 f2 = new Fragment2();
return f2;
case 2:
Fragment3 f3 = new Fragment3();
return f3;
case 3:
Fragment4 f4 = new Fragment4();
return f4;
case 4:
Fragment5 f5 = new Fragment5();
return f5;
}
return null;
}
#Override
public int getCount() {
// Show 5 total pages.
return 5;
}
}
Fragemnt class code :
public class F1 extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#SuppressLint("NewApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.f1,container, false);
Toast.makeText(getActivity(), "F1", Toast.LENGTH_SHORT).show();
return view;
}
}
The FragmentPagerAdapter keeps additional fragments, besides the one shown, in resumed state. The solution is to implement a custom OnPageChangeListener and create a new method for when the fragment is shown.
1) Create LifecycleManager Interface
The interface will have two methods and each ViewPager’s Fragment will implement it. These methods Are as follows:
public interface FragmentLifecycle {
public void onPauseFragment();
public void onResumeFragment();
}
2) Let each Fragment implement the interface
Add iplements statement for each class declaration:
public class FragmentBlue extends Fragment implements FragmentLifecycle
public class FragmentGreen extends Fragment implements FragmentLifecycle
public class FragmentPink extends Fragment implements FragmentLifecycle
3) Implement interface methods in each fragment
In order to check that it really works as expected, I will just log the method call and show Toast:
#Override
public void onPauseFragment() {
Log.i(TAG, "onPauseFragment()");
Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
#Override
public void onResumeFragment() {
Log.i(TAG, "onResumeFragment()");
Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
4) Call interface methods on ViewPager page change
You can set OnPageChangeListener on ViewPager and get callback each time when ViewPager shows another page:
pager.setOnPageChangeListener(pageChangeListener);
5) Implement OnPageChangeListener to call your custom Lifecycle methods
Listener knows the new position and can call the interface method on new Fragment with the help of PagerAdapter. I can here call onResumeFragment() for new fragment and onPauseFragment() on the current one.
I need to store also the current fragment’s position (initially the current position is equal to 0), since I don’t know whether the user scrolled from left to right or from right to left. See what I mean in code:
private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
int currentPosition = 0;
#Override
public void onPageSelected(int newPosition) {
FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
fragmentToShow.onResumeFragment();
FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
fragmentToHide.onPauseFragment();
currentPosition = newPosition;
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
public void onPageScrollStateChanged(int arg0) { }
};
I didn't write the code. Full tutorial here: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-including-source-code/
Use this
viewPager.setOffscreenPageLimit(1); // the number of pages you want to load in background
and also a ProgressDialogue.
ViewPager creates views for fragments adjacent to your current page. This also gives you an opportunity to load any data required for the adjacent fragments. If you are using AsyncTasks to load data, using this feature will result in a better user experience. But if you need an event when a particular page is opened by the viewpager, LordRaydenMK's solution will work.
See my post on the following thread for using AsyncTasks in a ViewPager:
AsyncTask runs on each page of the ViewPager
Hi You can try by using tag of each fragment and call method of each fragment on Page Changed
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
actionBar.setTitle(getHomePageTitle(position));
Fragment f = getFragrmentManager().findFragmentByTag(
"" + position);
if (f != null)
f.refresh();
}
});
and on
#Override
public Fragment getItem(int position) {
Fragment f=null;
switch (position)
{
case 0:
f = new Fragment1();
break;
case 1:
f = new Fragment2();
break;
case 2:
f = new Fragment3();
break;
case 3:
f = new Fragment4();
break;
case 4:
f = new Fragment5();
break;
}
f.setTag(""+position);
return f;
}

Strange onPause(), onResume() behaviour in fragments

The application has a main activity (MainActivity.java) with three tabs (fragments). I can navigate between them using the swipe left (riht) or clicking on a specific tab.
Upon starting the application, the 1st fragment is shown.
If I go to the 2nd fragment from the 1st fragment and then back to the 1st fragment, nothing happens (onResume() of the 1rd fragment isn't called), so it doesn't refresh it's content.
If I go to the 3rd fragment from the 1st fragment and then directly back to the 1st fragment, the onCreateView() of fragment1 is created and it's onResume() is called, which is correct.
If I go from the 3rd fragment to the 2nd fragment, the onCreateView() and onResume() of fragment1 are called, but not the onCreateView of fragment2.
I guess the logic in MainActivity isn't right, so I would kindly ask someone to take a look and tell me what could be wrong.
MainActivity.java:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
CollectionPagerAdapter mCollectionPagerAdapter;
public TTSocket socket;
DBHandler db;
public String logged_user;
private LogedinPerson person;
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bundle extras = getIntent().getExtras();
logged_user = extras.getString("logged_user");
socket = TTSocket.getInstance();
socket.currentRef = this;
db = new DBHandler(this);
person=db.getLogedInPerson();
socket.dbHandler=db;
socket.person=person;
if(!socket.isInit){
String typeInitStr = "{\"Type\":\"Init\", \"UserId\":\""+ person.getUserId() +"\"}";
socket.Send(typeInitStr);
}
mCollectionPagerAdapter = new CollectionPagerAdapter(getSupportFragmentManager());
// Set up action bar.
final ActionBar actionBar = getActionBar();
// Specify that we will be displaying tabs in the action bar.
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set up the ViewPager, attaching the adapter and setting up a listener
// for when the
// user swipes between sections.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCollectionPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
Log.d("TEST",position+"");
// the corresponding tab.
// We can also use ActionBar.Tab#select() to do this if
// we have a reference to the Tab
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mCollectionPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter.
// Also specify this Activity object, which implements the
// TabListener interface, as the
// listener for when this tab is selected.
if(i == 0){
actionBar.addTab(actionBar.newTab()
.setIcon(R.drawable.messages)
.setTabListener(this));
}else if(i == 1){
actionBar.addTab(actionBar.newTab()
.setIcon(R.drawable.contacts)
.setTabListener(this));
}else{
actionBar.addTab(actionBar.newTab()
.setIcon(R.drawable.history)
.setTabListener(this));
}
}
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
socket.currentRef = this;
socket.dbHandler=db;
socket.person=person;
//mCollectionPagerAdapter.notifyDataSetChanged();
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the primary sections of the app.
*/
public class CollectionPagerAdapter extends FragmentPagerAdapter {
final int NUM_ITEMS = 3; // number of tabs
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
/*
#Override
public Fragment getItem(int i) {
Fragment fragment = new TabFragment();
Bundle args = new Bundle();
args.putInt(TabFragment.ARG_OBJECT, i);
fragment.setArguments(args);
return fragment;
}
*/
#Override
public Fragment getItem(int position) {
Fragment fragment = new Fragment();
Bundle args = new Bundle();
args.putInt(TabFragment.ARG_OBJECT, position);
switch (position) {
case 0:
Log.i("Fragment", "0");
fragment = new Tab1Fragment();
fragment.setArguments(args);
return fragment;
case 1:
Log.i("Fragment", "1");
fragment = new Tab2Fragment();
fragment.setArguments(args);
return fragment;
case 2:
Log.i("Fragment", "2");
fragment = new Tab3Fragment();
fragment.setArguments(args);
return fragment;
default:
break;
}
return fragment;
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public CharSequence getPageTitle(int position) {
String tabLabel = null;
switch (position) {
case 0:
tabLabel = getString(R.string.label1);
break;
case 1:
tabLabel = getString(R.string.label2);
break;
case 2:
tabLabel = getString(R.string.label3);
break;
}
return tabLabel;
}
}
/**
* A fragment that launches other parts of the demo application.
*/
public static class TabFragment extends Fragment {
public static final String ARG_OBJECT = "object";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle args = getArguments();
int position = args.getInt(ARG_OBJECT);
int tabLayout = 0;
switch (position) {
case 0:
tabLayout = R.layout.tab1;
break;
case 1:
tabLayout = R.layout.tab2;
break;
case 2:
tabLayout = R.layout.tab3;
break;
}
View rootView = inflater.inflate(tabLayout, container, false);
return rootView;
}
}
}
Strange onPause(), onResume() behaviour() in fragments
It's not strange behaviour but native behaviour of ActionSherlock. This kind of behaviour is used for caching -> optimalisation for older devices with lower RAM this is reason why fragments are cached.
If you need to update content of fragment don't try to replace its layout or something similar. If you want to update fragment when scrolling between pages, you need to use method of FragmentPagerAdapter:
#Override
public int getItemPosition(Object object) {
// implementation
return super.getItemPosition(object);
}
This method is called when you will call
notifyDataSetChanged();
on your FragmentPagerAdapter. It's handy method for make updates of your fragments. There are more ways how to do it but here i'll show you how I'm doing it.
Let your fragments implement interface for example called Updateable:
interface Updateable {
public void update();
}
public class MyFragment extends SherlockFragment implements Updateable {
#Override
public void update() {
// perform Fragment updates
}
}
And in this method you will perform updates. Now back to getItemPosition() method. This method will be used for invoking update() method from Fragment i.e:
#Override
public int getItemPosition(Object object) {
Fragment f = (Fragment) object;
// determine which fragment
if (f instanceof MyFragment) {
((MyFragment) f).update(); // invokes update() method
}
return super.getItemPosition(object);
}
Now whenever you scroll page or tap on some tab (you need also call notifyDataSetChanged()) you are able to make Fragment updates. This way is more efficient against destroying and recreating fragment(s) each time you scrolling or clicking on tabs. But how i said this is not only solution there are more possible solutions.
Note: getItemPosition() can return two values: POSITION_NONE and UNCHANGED. Difference between both is that first indicates that Fragment will be always destroyed and recreated that is not very efficient and second indicates that Fragment won't be changed (is in on right place).
For more detailed explanation look here.
That is because ViewPager doesn't hide all fragments you switch.
You can control this behaviour by setOffscreenPageLimit

Categories

Resources