hi mate i have to know when a page is no longer the current.
i think that i have to use Listener, i see that exist:
#Override
public void onPageSelected(int position) {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
but there arent listener to know when page X is no longer active
I think you can use onPageScrolled method to understand that the active page was changed.
From the documentation:
This method will be invoked when the current page is scrolled, either as part of a
programmatically initiated smooth scroll or a user initiated touch scroll.
Therefore onPageScrolled method should do the trick.
Not sure what you mean by "no longer active" but the onPageSelected gives the new index so you could do something like this:
private currentPage = 0;
public void onPageSelected(int position) {
if(position != currentPage){ //page has changed to
currentPage = position;
}
}
Related
CONTEXT:
I have one activity, 4 fragments and a viewPager (each page consists of one fragment). Each fragment contains a list of short sounds (max 5 seconds each). The expected behavior is: if the user clicks on a sound on a certain page and the sound did not finish playing, if the user swipes to another page, the media player will be released, thus the sound will stop playing.
ISSUE:
When swiping left or right, the method onPause or onStop are not called (since the viewPager by definition loads the current, the previous and the next page), thus the media player playing the sound from the last page does not stop on swipe.
RESEARCH:
I have searched a lot on multiple posts, related to onPageChangeListener, setOffScreenPageLimit, set MediaPlayer not in fragment but in the activity (not possible in my case, since I have lists of sounds with adapter). Here are some links that I researched but did not solve my problem: ViewPager swipe previous sound, Multiple video players in viewpager in android, Android MediaPlayer on ViewPager blocking UI transition and no callback for initial page loads, How to handle MediaPlayer object inside a fragment inside view pager, Using Viewpager with MediaPlayer
SUGGESTIONS?: if you have any suggestions on how to tackle this issue, it would be highly appreciated! Thanks!
You can create a Callback interface on your MainActivity with a method onPageChanged() like this:
public interface Callback {
void onPageChanged();
}
Then, you can use this OnPageChangeListener:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private int currentPage = 0;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Fragment fragment = adapter.getItem(currentPage);
if (fragment instanceof Callback &&
currentPage != position) {
((Callback)adapter.getItem(currentPage)).onPageChanged();
}
currentPage = position;
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Each and every Fragment in your ViewPager can be created like this:
public class TestFragment extends Fragment implements MainActivity.Callback {
private void releaseMediaPlayer() {
// ...
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// ...
}
#Override
public void onPageChanged() {
releaseMediaPlayer();
// You can do more things here
}
}
After doing that, every time that you change the Fragment on the ViewPager it will be calling the onPageChanged method on the previous Fragment, and in there you can release your media player and do any other operation that you require.
private int currentPos = 0;
private int prevPos = -1;
global variable
I am getting same problem. I have take two method play and stop in fragment. and call below code in onPageSelected(int position)
new Thread(new Runnable() {
#Override
public void run() {
try {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
prevPos = currentPos;
currentPos = position;
MyFragment fragment = (MainFragment) getChildFragmentManager().
findFragmentByTag("android:switcher:" + R.id.viewPagerVideo + ":" + prevPos);
if (fragment != null) {
fragment.stop();
}
fragment = (MyFragment) getChildFragmentManager().
findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + currentPos);
if (fragment != null) {
fragment.play(mListUrl.get(position));
}
}
});
} catch (Exception ignore) {
}
}
}).start();
Consider you making the fragment itself an OnPageChangeListener. Then you can set the listener when you attach the page. This will allow you to pass the page change information to the fragment. You are allowed to have more than one OnPageChangeListener. Hope that helps.
EDIT:
Consider something like this.
public class PageFragment extends Fragment implements ViewPager.OnPageChangeListener {
ViewPager pager;
public void onPageScrollStateChanged (int state){
// reset the player if needed. you can do this since player object is in this class
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
....
pager = (ViewPager) getActivity().findViewById(ViewPagerId);
pager.addOnPageChangeListener(this);
....
}
#Override
public void onDestroyView (){
....
pager.removeOnPageChangeListener(this);
....
}
}
I have used viewpager with pagertabstrip
I have called webservice in onpageselected but while moving to category every category trying to load so the scrolling was not moving smoothly.Is there any way to achieve only load webservice when category moved?
You can use following listener in which there is a method called onPageSelected(int position) you can handle your fragment or web service calling based on the position.
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) {
}
});
At the moment, i have a viewpager,when page scroll,i have load api for get new information.
But in the first load viewpager,progress loading display two twice because it load first page and next page.
I only want to load the first page in viewpager.
How must I do?
best way is to create one interface. and implement this interface to all fragment.
e.g.
public interface FragmentInterface {
void fragmentBecameVisible();
}
in ur viewpager activity put like this e.g
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageSelected(int position){
FragmentInterface fragment = (FragmentInterface) mAdapter.instantiateItem(viewPager, position);
if (fragment != null) {
fragment.fragmentBecameVisible();
}
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2){
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
in your fragment like
public class TestFragmet extends Fragment implements FragmentInterface {
#Override
public void fragmentBecameVisible() {
// your task to execute
}
}
Put OffScreenPageLimit to ZERO. It won't load other fragments.
viewPager.setOffscreenPageLimit(0);
I have an android project that is using fragments and a viewpager.
I am using a separate countdown timer for every page, that only runs when the view of the page is 'onscreen'. At first the time for every page is the same, but after a while page 1 might be 20 seconds left, page 2 60 seconds and so on.
My problem is that I don't know how to save the remaining time, the moment the user swipes to the next page. I am using a onpagestatelistener that has the following code, but this is saving the new value of questionId and the old value of the new time. How do I refer to the value of the questionId and the matching newtime-value of the page that was in view before the user swiped?
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
saveTime();
}
}
public void onPageScrolled(int position, float arg1, int arg2) {}
public void onPageSelected(int pos) {
questionId = mQuestions.get(pos).getNr()
runTime();
}
});
public void saveTime(){
mQuestions.get(questionId).setTime(newTime);
}
public void runTime(){
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
mTimer = new CountDownTimer(90000, 1000) {//MillisInFuture, countDownInterval
public void onTick(long millisUntilFinished) {
newTime = (millisUntilFinished/1000);
}
public void onFinish() {
}
}.start();
}
First of all you can use SharedPreferences.
Besides, of course you can save data in adapter which you use for ViewPager, you can save this data in DB or create some singleInstance in your parent Activity or Fragment.
Is there any way for me to invoke a callback when the user swipes from one pane to the next? As far as my experimentation has revealed, the present (primary) pane/fragment as well as the adjacent two (to the left and right) are all 'resumed', so none of the regular fragment lifecycle callbacks are invoked. I'm interested in this in order to hide a MediaController as soon as the pane it's associated with has been left.
You can attach an OnPageChangeListener to your ViewPager to get updates on when the user swipes to a new page:
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int state)
{
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
#Override
public void onPageSelected(int position)
{
Log.d("MainActivity", "New position = " + position);
}
});
And if you use a FragmentPagerAdapter, your ViewPager's pages will be cached in memory. If you use a FragmentStatePagerAdapter, they will not be cached.
the Fragment's setUserVisibleHint() would be callback as long as a fragment was completely disappeared or appeared, hide or show the MediaController operation can be done here.
public class YourFragment extend android.support.v4.app.Fragment {
...
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
System.out.println("VISIBLE");
} else {
System.out.println("GONE");
}
}
...
}