actually i have 4 fragments in my app and i switch the fragments by swiping left or right. I used view pager for swiping the fragments are swiping perfectly but there is a problem if i swipe and fragment B shows but the backend functionality of fragment C runs. If i go to C then backend functionality of D runs. At fragment A first backend functionality of fragment A runs then it automatically shifted to fragment B but front end view is of fragment A
This is adapter
public class TabsPagerAdapter extends FragmentPagerAdapter {
private int mNumTabs;
public TabsPagerAdapter(FragmentManager fm, int numTabs) {
super(fm);
this.mNumTabs= numTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
PersonalSettings tab0 = new PersonalSettings();
return tab0;
case 1:
Health tab1 = new Health();
return tab1;
case 2:
Statistics tab2 = new Statistics();
return tab2;
case 3:
Motivation tab3 = new Motivation();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumTabs;
}
}
This is main activity
viewPager = (ViewPager) findViewById(R.id.pager);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),4);
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
If u want further code i will give u
It because the viewpager will preload the item next to the current item to improve UX (in your case, the item is the fragment)
You can set offscreenPageLimit to ViewPager to limit it:
viewPager.setOffscreenPageLimit(1);
But if you do this, you will found the fragment will reload everytime you enter, IMO this is not a good practice.
Override destroyItem method in FragmentpagerAdapter
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
// remove your fragment obj from here
}
Related
I have a HomeActivity where I have used ViewPager. There are 2 fragments home1F and home2F that come when swipe right. The HomeActivity has a top bar (used by Linerlayout) where there are 2 imagebuttons. When home1F is in the screen one button is shown(other is invisible) and when home2F is in the screen the other button is shown while the first one becomes invisible.
But when I run the app I find at first the second button is visible instead of the first one (when there is home1F). When i swipe to home2F nothing happens. When I swipe left to come back to home1F still nothing happens.
Here is the code:
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0:
//imagebutton-1 visible
//imagebutton-2 invisible
return Home1F.newInstance("FirstFragment, Instance 1");
case 1:
//imagebutton-1 invisible
//imagebutton-2 visible
return Home2F.newInstance("SecondFragment, Instance 1");
default:
//imagebutton-1 visible
//imagebutton-2 invisible
return Home1F.newInstance("FirstFragment, Instance 1");
}}
#Override
public int getCount() {
return 2;
}
}
Try this
Show the imageButton1 and hide the imageButton2 in onCreate of your Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
imag1.setVisibility(View.VISIBLE);
imag2.setVisibility(View.GONE);
So when your app launch it will show the first imageButton and hide the second imageButton
Now when you switch between tabs
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position==0){
imag1.setVisibility(View.VISIBLE);
imag2.setVisibility(View.GONE);
}
else if(position==1){
imag1.setVisibility(View.GONE);
imag2.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
if you want to switch out the actual fragments that are being displayed, you need to avoid FragmentPagerAdapter and use FragmentStatePagerAdapter.
using getItemPosition() we can update the fragments. In below example have updated fragment titles :
ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();
FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
public int getCount() {
return titles.size();
}
public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
fragment.setTitle(titles.get(position));
return fragment;
}
public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
});
I am using view pager which is having 3 fragments
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private static final String TAG="ViewPageAdapter";
private final int PAGES = 3;
private String[] title = new String[]{"Frag1",
"Frag2", "Frag2"};
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.d(TAG, "position is " + position);
switch (position) {
case 0:
return new Frag1();
case 1:
return new Frag2();
case 2:
return new Frag3();
default:
throw new IllegalArgumentException(
"The item position should be less or equal to:" + PAGES);
}
}
#Override
public int getCount() {
return PAGES;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return title[position];
}
}
I am setting view pager from main activity:
viewPageAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.addOnPageChangeListener(onPageChangeListener);
viewPager.setAdapter(viewPageAdapter);
When i execute viewPageAdapter.notifyDataSetChanged();
or viewPager.setAdapter(viewPageAdapter); method to recreate fragments the activity is getting destroyed.don't know what causing the issue.
I checked many solution nothing worked.
ViewPager PagerAdapter not updating the View
Update ViewPager dynamically?
I am asking another problem because which is related to above question.
The problem which is described in link
ViewPager onPageSelected for first page
where i am not able to get first page tab title on load.i am using android.support.v4.view.PagerTabStrip
Please help me in getting solved. Wasted my whole day to get rid of this :(
I have created a simple app with 3 tab TAB1, TAB2, TAB3
When i select the TAB1 adjacent TAB2 get loaded into memory after that when i press on the TAB2 or TAB3 my content on the TAB2 will not get refresh.
If i click tab in the sequence TAB1->TAB2->TAB1->TAB2 my fragment will not refresh
I want load the selected tab each time when i select the tab.
I am using the following code to load the fragment on tab selected
public class SampleFragmentPageAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"HOME", "BEACON", "NEARBY"};
private int[] imageResId = {
R.drawable.home,
R.drawable.beacon,
R.drawable.nearby
};
private Context context;
public SampleFragmentPageAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0)
fragment = new FragmentTab1();
if (position == 1)
fragment = new FragmentTab2();
if (position == 2)
fragment = new FragmentTab3();
return fragment;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
Drawable image = context.getResources().getDrawable(imageResId[position]);
image.setBounds(0, 0, 32, 32);
// Replace blank spaces with image icon
SpannableString sb = new SpannableString(" " + tabTitles[position]);
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
return super.instantiateItem(container, position);
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
}
Your_Pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == WHATEVER) {
//do your Staff
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
You can visit here for more information
http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html
FragmentPagerAdapter:
FragmentPagerAdapter stores the whole fragment in memory, and could increase a memory overhead if a large amount of fragments are used in ViewPager.
FragmentStatePagerAdapter:
FragmentStatePagerAdapter only stores the savedInstanceState of fragments, and destroys all the fragments when they lose focus. Therefore FragmentStatePagerAdapter should be used when we have to use dynamic fragments, like fragments with widgets, as their data could be stored in the savedInstanceState
USE CASES:
FragmentPagerAdapter should be used when we need to store the whole fragment in memory. When I say the whole fragment is kept in memory it means, its instances wont be destroyed and would create a memory overhead. Therefore it is advised to use FragmentPagerAdapter only when there are low number of fragments for ViewPager. It would be even better if the fragments are static, since they would not be having large amount of objects whose instances would be stored.
In your case if your using Listview, recyclerview or any heavy work you should use 'FragmentStatePagerAdapter' other wise 'FragmentPagerAdapter'
i want to set different pages for ViewPager from class. for example:
i have 4 activity A + B + C and D.
A include my ViewPager.
B +C + D are different pages that must be shown in ViewPager.(each of them have different contex)
my question is that, how can i recognize these pages into ViewPager?
thanks
You can add but better way is that you will create a activity and your four activity should be child fragment of the same .
In short your all activity should be fragments jst load the fregment when you swipe viewpage indicater
sample code for adapter
//User adapter according condition
final FragmentPagerAdapter adapter = new FragmentChildPageAdapter(getChildFragmentManager());
//final FragmentPagerAdapter adapter = new FragmentChildPageAdapter(getActivity().getSupportFragmentManager()));
final ViewPager pager = (ViewPager) v.findViewById(R.id.pager);
pager.setAdapter(adapter);
final TabPageIndicator indicator = (TabPageIndicator) v.findViewById(R.id.indicator);
indicator.setViewPager(pager);
//Adapter
class FragmentChildPageAdapter extends FragmentPagerAdapter implements
IconPagerAdapter {
public FragmentChildPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
//first fregment
break;
case 1:
//Second fregment
break;
case 2:
//third fragment
break;
case 3:
//Forth fragment
break;
}
return fragment;
}
#SuppressLint("DefaultLocale")
/*#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}*/
#Override
public int getCount() {
//return CONTENT.length;
return CONTENT.size();
}
#Override
public int getIconResId(int position) {
return (Integer) Icon.get(position % CONTENT.size());
}
}
I've been trying to update a listview on my second position of a viewpager when checking a "favourite" checkbox on the listview using an interface. It's working as expected but when I go to the 3rd Fragment and then swipe back again the favourites doesn't update even though everything seems like it should work as before doesn't work until i rotate or restart the app.
I've checked the fragmentmanager and it does contain only three Fragments all the time and the methods do get called (register as if the listview should be changed like it does before i swipe to the 3rd tab and back), so I'm really scratching my head here.
FragmentStatePageAdapter:
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
/* Some irrelevant code */
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return FragmentList.newInstance();
case 1:
return FragmentFavourites.newInstance();
case 2:
return FragmentThree.newInstance();
default:
return FragmentList.newInstance();
}
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
#Override
public int getCount() {
return 3;
}
Activity (callback):
#Override
public void favouritesChangedFromMainMenu() {
FragmentFavourites favouritesList = (FragmentFavourites) mSectionsPagerAdapter.getRegisteredFragment(1);
if(null != favouritesList) {
favouritesList.favouritesChangedFromMainMenu();
}
}
When you move to the third fragment, the first one is probably killed (with a call to onSaveInstanceState).
Solution 1, yourViewPager.setOffscreenPageLimit(2);
Solution 2, check if your first fragment is killed... and re-created when you swipe and re-create correct link that you do in onCreate.