Fragment-based app using ViewPager (Android Studio Template) creates off-screen fragments - android

I created a new project in Android Studio that uses fragments and tabs to select a fragment.
So Android Studio created a project for me that uses a ViewPager to select the different fragments.
Unfortunately, ViewPager will create off-screen fragments and even trigger onResume() in the off-screen fragment !
This is a problem, since code in onResume() in fragment 2 depends on what a user does in fragment 1.
I've tried setting mViewPager.setOffscreenPageLimit(0); but this doesn't seem to have any effect, the neighboring fragment is still called with onResume() before it's actually shown.
QUESTION
What callback is triggered in a Fragment when it's actually shown?
Otherwise, how can I set it up so that I can adjust the UI in fragment 2 depending on what the user did in Fragment 1 ?

you can use setOnPageChangeListener() like this
mViewPager.setOffscreenPageLimit(1);
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {
// TO DO
}
#Override
public void onPageScrollStateChanged(int state) {}
});

Related

Android: ViewPager + Fragments: modify fragment view when "onPageScrolled"

Well, I think the title is quite self explanatory. I have a ViewPager in my HomeActivity, the ViewPager contains 5 fragments at the moment.
When one of the fragments is visible by calling ViewPager's onPageScrolled I want to modify some views inside the current displayed fragment according to some conditions in the HomeActiviy.
After some research, it seems like I cannot find a good way to communicate in the direction HomeActivity --> Fragments inside ViewPager.
I have easily solved the communication in the direction Fragments in ViewPager --> HomeActivity using an Interfacebut this trick seems to not be working on the other direction.
I can access each time the current displayed fragment using a method on my FragmentStatePagerAdapter
public Fragment getActiveFragment(int position){
return myFragmentsList.get(position);
}
However, by doing that, I would have to cast each Fragment into its class MyFragment1 MyFragment2 MyFragment3....
Any easy clean way to achieve that?. Here is the relevant portion of the code:
mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (currentStatus == 1){
Fragment activeFrag = mPagerAdapter.getActiveFragment(mPager.getCurrentItem());
//here I would like to modify one of the 5 fragments
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
});
Define an interface,
interface FragmentListenerInterface {
public void onFragmentSelected();
}
Implement this interface in all of your fragments. change the communication between fragment and viewpager. write a method to return fragmentlistenerinterface instead of fragment.
public FragmentListenerInterface getActiveFragment(int position){
return (FragmentListenerInterface) myFragmentsList.get(position);
}
After this just say, in your code
public void onPageSelected(int position) {
mViewPager.getActiveFragment(position).onFragmentSelected();
}
And implement onFragmentSelected() in every fragment.

When should a Fragment's onActivityCreated be called?

I have a few Fragments in a ViewPager, and I've found the Fragment's onActivityCreated and onCreateView are both being called on the page before I expect.
For example, when the ViewPager transitions from page 2 to 3, then the Fragment at page 4's onCreateView and onActivityCreated are being called.
I'm intending to initiate a network request in onActivityCreated but it is starting one screen too soon. According to the Android docs, onActivityCreated is called "when the fragment's activity has been created and this fragment's view hierarchy instantiated." which leads me to believe I'm using the method correctly.
For smooth loading of data view pager will load the fragments in advance.
1. If you are at 1st position(first fragment),so its automatically loads the next 2 fragments
2.Or if you are at 2 or later,then it will load previous one fragment and next fragment
ViewPager loads the next fragment for smooth transition between fragments, and that's why your next fragment's onCreate(), onCreateView() and onResume() is getting called.
So, add onPageChangeListener on your viewPager like:
yourViewPager.addOnPageChangeListener(new OnPageChangeListener{
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {
switch(position){
//your code for network operation
}
}
#Override
public void onPageScrollStateChanged(int state) {}
});
As others have mentioned, this is done for smooth loading of data in a view pager. What you can do though is call your code in onAattach() or when your fragment is visible to the user in onStart(). Android docs gives more details on lifecycle methods.

Where to put "ViewPager.setCurrentItem()" Method

I have Nested Fragments [1 main Fragment called "MainFrag" and many child Fragments]
the App can show MainFrag or can show other fragments.
what I want to do is to setCurrentItem of MainFrag's ViewPager every time the user selects to show that MainFrag so I tried to put it at it's onCreateView but this only works for the first time the User Shows MainFrag as if user Selects another fragment and then re-selects MainFrag the seCurrentItem is not working
I also tried to put it inside MainFrag's onResume, It worked as required but it also causes a problem that if the user moved the App to background and then reOpen it viewPager will Scroll and i don't want this
So where Exactly Can I put setCurrentItem ?
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
Edit: I am using Navigation Menu to Move between 3 main fragments where MainFrag is one of them.
After your mViewPager.setAdapter(adapter); method you can put
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
After setting adapter to viewpager add setCurrentItem method
mViewPager.setAdapter(adapter);
mViewPager.setCurrentItem(mCurrentWeekFragmentItemNumber);
Try this:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
viewPager.setCurrentItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}

Android: when to set Toolbar title form Fragment?

I have a ViewPager that contains some Fragments.
I need to update the title on the Activity Toolbar when the fragment changes.
In which lifecycle method of the Fragment should I call the Activity to set the new title?
It would be nice to use setUserVisibleHint(true), but sometimes it gets called when the Activity is not actually ready (Toolbar is null).
And additionally I need to manage the config change and need to makes sure that the title in the Toolbar is the one of the Fragment currently displayed.
Thanks
I think the better option is do that in onPageSelected()
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});

Is there a tabLoaded callback in an android viewpager?

Currently I'm building an app with different tabs in it. In one of the tabs I have a camera fragment that I start and show to the user. To implement smooth swiping I want to load the tab content itself, so that the user his swiping doesn't hang. When it's loaded the camera should be started.
Is there some sort of a callback/listener/trick that can be used to see if a fragment is fully loaded?
Tab layout is bound to view pager using tablayout.setupWithViewPager(viewPager), so you can use view pager page listener to detect tab loaded event.
Official Documentation
If you're using a ViewPager together with TabLayout, you can call setupWithViewPager(ViewPager) to link the two together.
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
//tab loaded
}
#Override
public void onPageScrollStateChanged(int state) {
}
});`
It appears that many people are using setOnPageChangedListener() on the ViewPager. We ended up implementing this after noticing a race condition due to Fragments not loading synchronously due to using the FragmentManager. Check out the answer here.
Which lifecycle callback is called when a fragment pager adapter's fragment comes to screen?

Categories

Resources