ViewPager recreate fragments all the time - android

I am using ViewPager with my fragments. All fragments has animation and it does not work when switching back maybe because ViewPager saves somehow state of near Fragments, do you have some idea how to avoid it?
getItemPosition() doesn't make anything in this case
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return GetStartedOneFragment.newInstance();
case 1:
return GetStartedTwoFragment.newInstance();
case 2:
return GetStartedThreeFragment.newInstance();
case 3:
return GetStartedFourFragment.newInstance();
case 4:
return GetStartedFiveFragment.newInstance();
case 5:
return GetStartedSixFragment.newInstance();
default:
return GetStartedOneFragment.newInstance();
}
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}

I used a Fragment as a slider content, see the sample code below. Feel free to ask more details if required.
I have 4 flight modes in the example. The ViewPager is used with the associated adapter (ScreenSlidePagerAdapter).
You can see the app in the Play Store to see the slider (search "Flight Recorder 24").
// In the main fragment java code
private View headerView;
private ViewPager mPager;
public ScreenSlidePagerAdapter mPagerAdapter;
// ...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
View mainView = inflater.inflate(R.layout.monitoring_fragment,container, false);
// The header of the list
View view = inflater.inflate(R.layout.header_monitoring_fragment, mListView, false);
headerView = view;
//...
mPager = (ViewPager) view.findViewById(R.id.pager);
FragmentManager fm = getChildFragmentManager();
mPagerAdapter = new ScreenSlidePagerAdapter(fm);
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(UserConfiguration.getUserConf().getPositionFromFlightMode());
// Attach the page change listener inside the activity
mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
// This method will be invoked when a new page becomes selected.
#Override
public void onPageSelected(int position)
{
int flight_mode = UserConfiguration.getFlightModeFromPosition(position);
UserConfiguration.getUserConf().setFlightMode(flight_mode);
}
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
// Code goes here
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int state)
{
// Code goes here
}
});
// ...
}
// ...
// Slider adapter
private class ScreenSlidePagerAdapter extends FragmentPagerAdapter
{
public ScreenSlidePagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
// position to flight mode
int flight_mode = UserConfiguration.getFlightModeFromPosition(position);
FlightModeFragment flightModeFragment = FlightModeFragment.newInstance(flight_mode);
return flightModeFragment;
}
public int getItemPosition(Object object)
{
return POSITION_NONE;
}
#Override
public int getCount()
{
return 4;
}
}
Then you have to create a Fragment with your slider content (here the class FlightModeFragment), it will be instanciated with an integer to identify the page embedded into a Bundle savedInstanceState (I have 4 pages).
public class FlightModeFragment extends Fragment
{
LinearLayout mainLayout;
ImageView live15minImageView;
ImageView modeImageView;
ImageView imageViewLeft;
ImageView imageViewRight;
private TextView textViewRecord;
private TextView textViewGps;
int flight_mode = UserConfiguration.AC_LISTENER_TRAVEL_RECORDER_MODE;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// handle fragment arguments
Bundle arguments = getArguments();
if(arguments != null)
{
flight_mode = arguments.getInt("flight_mode");
}
}
// ...
}

Related

Android ViewPager inside Fragment loaded only once v2

My question is similtar to this:
Android ViewPager Inside Fragment Loaded Only Once
The difference is that its answer doesn't work for me.
I have 4 fragments. Inside one of these fragments there is a Fragment X with ViewPager that switch betwen two other fragments. The first time I load the FragmentX the ViewPager works fine. The problem is if I switch to one of the other 4 fragments, when I go back to the FragmentX the ViewPager has nothing inside.
Fragment X
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_campus, container, false);
TabLayout tabLayout = (TabLayout)view.findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Mapa"));
tabLayout.addTab(tabLayout.newTab().setText("Eventos"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
vpPager = (ViewPager)view.findViewById(R.id.vpPager);
adapterViewPager = new PagerAdapter(getChildFragmentManager());
vpPager.setAdapter(adapterViewPager);
vpPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
vpPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
return view;
}
PageAdapter
public class PagerAdapter extends FragmentPagerAdapter {
private int NUM_ITEMS = 2;
public PagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Returns total number of pages
#Override
public int getCount() {
return NUM_ITEMS;
}
// Returns the fragment to display for that page
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return MapFragment.newInstance(0);
case 1:
return EventosFragment.newInstance(1);
default:
return null;
}
}
// Returns the page title for the top indicator
#Override
public CharSequence getPageTitle(int position) {
return "Page " + position;
}
}
MainActivity
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
...
if (...) {
if (campusFragment == null) // the problem is not solved by commenting this condition
campusFragment = new CampusFragment(); // Fragment X
fragmentManager.beginTransaction().replace(R.id.content_frame, campusFragment).commit();
}
}

How to prevent Fragment from loading data every time from server when swiping Tabs in TabLayout in android?

I am a newbie with Fragments. I have 5 different Fragmentsin my TabLayout. In each fragment I am loading data from the server.
My problem is as follows:
When the first fragment loads it calls the function and loads data from the server and displays on the RecyclerView.
Then When I swipe to the second tab the server data loads and so on. But when I swipe again to say fragment one the data is loading again from the server and the RecyclerView needs to be set again.
Is there anyway where I can load the server data only once (without saving it to a local database) and set the recyclerview only once so that no matter how many times I swipe the tab the data does not load again? I have referred here but i really didnt understand how to solve my problem.I am posting a snippet of my code.
TabActivity
public class TabActivity extends AppCompatActivity {
ViewPager viewpager;
Toolbar toolbar;
TabLayout tablayout;
ViewPagerAdapter viewPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_activity);
initialize();
}
private void initialize() {
viewpager = (ViewPager) findViewById(R.id.viewpager);
toolbar = (Toolbar) findViewById(R.id.toolbar);
tablayout = (TabLayout) findViewById(R.id.tablayout);
setSupportActionBar(toolbar);
viewPagerAdapter=new ViewPagerAdapter(getSupportFragmentManager());
viewpager.setAdapter(viewPagerAdapter);
tablayout.setTabsFromPagerAdapter(viewPagerAdapter);
tablayout.setupWithViewPager(viewpager);
}
}
class ViewPagerAdapter extends FragmentStatePagerAdapter implements ViewPager.OnPageChangeListener {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:return LocatedEvents.newInstance();
case 1:return QrCodeScanner.newInstance();
case 2:return NewsFeed.newInstance();
case 3:return CreatePoll.newInstance();
case 4:return MyProfile.newInstance();
}
return NewsFeed.newInstance();
}
#Override
public int getCount() {
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
return "Tab " + (position + 1);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
NewsFeed Fragment
public class NewsFeed extends Fragment {
#Nullable
public static NewsFeed newInstance() {
return new NewsFeed();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.newsfeed_fragment, container, false);
load_data();
return view;
}
}
Avoid creating new Fragments every time in
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return LocatedEvents.newInstance();
case 1:
return QrCodeScanner.newInstance();
case 2:
return NewsFeed.newInstance();
case 3:
return CreatePoll.newInstance();
case 4:
return MyProfile.newInstance();
}
return NewsFeed.newInstance();
}
Make an array of fragments and pass it to your Adapter.Something like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
initFragments();
}
private void initFragments() {
ArrayList < Fragment > fragmentArrayList = new ArrayList < > ();
fragmentArrayList.add(LocatedEvents.newInstance());
fragmentArrayList.add(QrCodeScanner.newInstance());
fragmentArrayList.add(NewsFeed.newInstance());
fragmentArrayList.add(MyProfile.newInstance();
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragmentArrayList); viewpager.setAdapter(viewPagerAdapter); tablayout.setTabsFromPagerAdapter(viewPagerAdapter); tablayout.setupWithViewPager(viewpager);
}
And in your adapter change it to
private ArrayList < Fragment > fragments;
public ViewPagerAdapter(FragmentManager fm, ArrayList < Fragment > fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}

PagerAdapter not called inside fragment when I move to the fragment for the second time in Android

I'm working with viewpager inside fragments. I'm using pagerAdapter to switch between two pages via XML. Here is the code:
public class DemoPagerAdapter extends FragmentPagerAdapter {
public DemoPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
Fragment f;
switch (index) {
case 0:
f = new FirstFragment();
break;
case 1:
f = new SecondFragment();
break;
}
return f;
}
#Override
public int getCount() {
return 2;
}
}
And I'm calling it like this:
public class DemoFragment1 extends Fragment {
private ViewPager viewPager;
private DemoPagerAdapter mAdapter;
public DemoFragment1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.security, container, false);
mAdapter = new DemoPagerAdapter(getActivity().getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
showPages(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
return rootView;
}
Everything works fine. But if I move to DemoFragment2 and then come back to DemoFragment1, PagerAdapter is not called.
Your ViewPager is nested in a Fragment, you should use the ChildFragmentManager, modify:
mAdapter = new DemoPagerAdapter(getChildFragmentManager());
I also assume the ViewPager will keep the off screen fragment in memory, thus it might not call getItem(int index) again. Add
viewPager.setOffscreenPageLimit(0);
return rootView;
Well, I encontered this issue last week.
When I put the ViewPager in the fragment with a FragmentPagerAdapter, after I move forward to anoter Fragment and back, the pager' s view not exists.
I supposed is the FragmentPagerAdapter won' t retain its view in the ViewPager ' s host Fragment, Their life cycle is not the same. Though you put the VewPager' s host Fragment in the back stack, but the FragmentPagerAdapter' s fragment not. And Then, I gave up FragmentPagerAdapter and tried android.support.v4.view.PagerAdapter, (note, it wont' t use fragment to inject view!), everything is fine!
below is the sample:
private final PagerAdapter coverPager = new PagerAdapter() {
private LayoutInflater mLayoutInflater;
#Override
public int getCount() {
return 2;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
if (mLayoutInflater == null) {
mLayoutInflater = LayoutInflater.from(getActivity());
}
switch (position) {
case 0:
View frontPage = mLayoutInflater.inflate(R.layout.profile_cover, container, false);
ImageView avatar = (ImageView) frontPage.findViewById(R.id.avatar);
Picasso.with(getActivity())
.load(mAvatarUrl)
.placeholder(R.drawable.error)
.error(R.drawable.error)
.into(avatar);
TextView screenName = (TextView) frontPage.findViewById(R.id.screen_name);
screenName.setText("#" + mScreenName);
TextView remark = (TextView) frontPage.findViewById(R.id.remark);
remark.setText(TextUtils.isEmpty(mRemark) ? mScreenName : mRemark);
if (mVerified) {
frontPage.findViewById(R.id.verified).setVisibility(View.VISIBLE);
}
container.addView(frontPage);
return frontPage;
case 1:
View introPage = mLayoutInflater.inflate(R.layout.profile_intro, container, false);
CatnutUtils.setText(introPage, R.id.description, TextUtils.isEmpty(mDescription)
? getString(R.string.no_description) : mDescription);
CatnutUtils.setText(introPage, R.id.location, mLocation);
CatnutUtils.setText(introPage, R.id.profile_url, Constants.WEIBO_DOMAIN + mProfileUrl);
container.addView(introPage);
return introPage;
default:
return null;
}
}
};
and then in your onViewCreate or OnCreateView, put mViewPager.setAdapter(coverPager);
the instantiateItem is the place to put the page' s view, similar like the FragmentPagerAdapter!
It' s just like put the FragmentAdapter' s view int the ViewPager' s host Fragment, not the other fragment!
Hope it' s helpful!

Android ViewPager in Fragment not updating

I have a Fragment for a ViewPager. The ViewPager is updated based on an action fired by the user. Well when the Fragment is recreated so to speak, the page of a ViewPager is not updated as should be, or even shown for that matter! When I swipe over to other pages and then back to that one, it loads?
Here is the Fragment:
public static class CardFrontFragment extends Fragment {
public CardFrontFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = null;
rootView = inflater.inflate(R.layout.activity_dashboard, container, false);
TextView textviewLocation = (TextView)rootView.findViewById(R.id.textview_location);
TextView textviewConditions = (TextView)rootView.findViewById(R.id.textview_points);
ViewPager viewPagerDashboard = (ViewPager)rootView.findViewById(R.id.viewPager_Dashboard);
if(overviewData != null) {
textviewLocation.setText(overviewData.getLocation());
textviewPoints.setText(overviewData.getPoints());
viewPagerDashboard.setAdapter(adapterSectionsPager);
adapterSectionsPager.notifyDataSetChanged();
viewPagerDashboard.destroyDrawingCache();
textviewLocation.setText(overviewData.getWeathersLocation());
textviewPoints.setText(overviewData.getWeathersConditions());
}
return rootView;
}
}
Here is the adapter:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
return DashboardSectionFragment.create
(uiContext, position, overviewData, forecastData, hourlyData, radarData);
}
#Override
public int getCount() {
// Show 4 total pages:
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section_1).toUpperCase(l);
case 1:
return getString(R.string.title_section_2).toUpperCase(l);
case 2:
return getString(R.string.title_section_3).toUpperCase(l);
case 3:
// Radar Page:
return getString(R.string.title_section_4).toUpperCase(l);
}
return null;
}
}
I heard I am extending the correct one FragmentStatePagerAdapter over FragmentPagerAdapter. Yet nothing is working. I have called many methods of the ViewPager and adapter in the Fragment when the ViewPager is recreated but it still does not load initially till it appears off screen then back on...
Thanks!
try overriding the following like this and update the viewpager and pageradapater instance
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
viewPager.invalidate();
pagerAdapter.notifyDataSetChanged();
}
or else depending upon the specific location of the Fragment you can do the following
#Override
public void onPageSelected(int arg0) {
if(int == 2)// In which specifi fragment you want to update the view
{
viewPager.invalidate();
pagerAdapter.notifyDataSetChanged();
}
}
I hope this would help you
Try to update view when fragment get visible to user as follows:
public class MyFragment extends Fragment
#Override
public void setMenuVisibility(final boolean visible) {
super.setMenuVisibility(visible);
if (visible) {
**//Update views here**
}
}

Android FragmentPagerAdapter showing up empty after cache clear

I make a FragmentPagerAdapter
There is a fragment which has a pager.
And the pager show 3 fragments and it works well.
But, After application cache clearing,
(It means... long time has passed application service backgrounded)
only pager showing up and 3 fragments have empty layout (white space).
As a result checking Log, I caught some problem lines...
After clearing cache, SectionsPagerAdapter() constructure called then
getItem() method never called.
Please Help me
public class ReviewFragment extends SherlockFragment {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.review_fragment, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) getActivity().findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new BFragment();
} else {
return new CFragment();
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "1";
case 1:
return "2";
}
return null;
}
}

Categories

Resources