I want to know that the ViewPagers View has scrolled half the screen or not?
While I am dragging it, if it has covered half the screen I want to change the page.
For e.g. if I am testing on MDPI, i.e. of screen width 320px, and if I drag my page of ViewPager by 160px then I want to change the page.
How to get this half distance covered by view from ViewPager?
Use OnPageChangeListener's methods. The onPageScrolled method returns positionOffset > 0.5 if user scrolled more than half of the screen.
http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html
I assume You want to update some static views when page is scrolled by half of screen without waiting for it to scroll full page width. Here is my solution for this problem using onPageScrolled callback.
#Override
public void onPageScrolled( int position , float positionOffset , int positionOffsetPixels )
{
if ( position == mCurrentSelectedScreen )
{
// We are moving to next screen on right side
if ( positionOffset > 0.5 )
{
// Closer to next screen than to current
if ( position + 1 != mNextSelectedScreen )
{
mNextSelectedScreen = position + 1;
updateStaticViewsForScreen( mNextSelectedScreen );
}
}
else
{
// Closer to current screen than to next
if ( position != mNextSelectedScreen )
{
mNextSelectedScreen = position;
updateStaticViewsForScreen( mNextSelectedScreen );
}
}
}
else
{
// We are moving to next screen left side
if ( positionOffset > 0.5 )
{
// Closer to current screen than to next
if ( position + 1 != mNextSelectedScreen )
{
mNextSelectedScreen = position + 1;
updateStaticViewsForScreen( mNextSelectedScreen );
}
}
else
{
// Closer to next screen than to current
if ( position != mNextSelectedScreen )
{
mNextSelectedScreen = position;
updateStaticViewsForScreen( mNextSelectedScreen );
}
}
}
}
#Override
public void onPageSelected( int arg0 )
{
updateStaticViewsForScreen( arg0 );
mCurrentSelectedScreen = arg0;
mNextSelectedScreen = arg0;
}
I agree with preious answer, but when I quick swipe and release on ViewPager, onPageSelected will be trigged before onPageScrolled and it will call updateStaticViewsForScreen 3 times and view blinks.
I upgrade solution with recording ViewPager's state:
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels )
{
if(mCurrentPagerState != ViewPager.SCROLL_STATE_SETTLING)
{
// one of previous code of onPageScrolled
}
}
#Override
public void onPageSelected( int position)
{
// one of previous code of onPageSelected
}
#Override
public void onPageScrollStateChanged(int state) {
mCurrentPagerState = state;
}
It can be achieved without mNextSelectedScreen. Do what you want on setPage().
private int mCurrentPage;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position == mCurrentPage) {
// It's gone to right.
if (positionOffset > 0.5) {
setPage(position + 1);
}
// Not yet.
else {
setPage(position);
}
} else {
// It's gone to left.
if (positionOffset < 0.5) {
setPage(position);
}
// Not yet.
else {
setPage(position + 1);
}
}
}
#Override
public void onPageSelected(int position) {
mCurrentPage = position;
setPage(position);
}
setonpagechangelistner event on view pager.
MyPagerAdapter adapter = new MyPagerAdapter(getApplicationContext());
myPager = (ViewPager)findViewById(R.id.myfivepanelpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
myPager.setOffscreenPageLimit(7);
myPager.setOnPageChangeListener(new MyPageChangeListener());
then
private class MyPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
/* (non-Javadoc)
* #see android.support.v4.view.ViewPager.SimpleOnPageChangeListener#onPageSelected(int)
*/
#Override
public void onPageSelected(int position) {
focusedPage = position;
switch (focusedPage) {
case 0:
break;
case 1:
Break;
}
}
here you can get the position of your current page.
Related
I have a viewpager with cards, that need to be swipeable to the right until the last item is reached, and swipeable to the left until the first item was reached. I don't know how to solve this.
SlidesPagerAdapter slidesPagerAdapter = new SlidesPagerAdapter(getFragmentManager());
viewPager.setAdapter(slidesPagerAdapter);
viewPager.setOffscreenPageLimit(3); // To see two cards the sides
viewPager.setClipToPadding(false);
viewPager.setPadding(32,0,32,0);
viewPager.setPageMargin(-16);
// Attach the page change listener inside the activity
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position > SlidesPagerAdapter.NUMBER_SLIDES-1) {
viewPager.setCurrentItem(0, true);
}
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int state) {
int currentPage = viewPager.getCurrentItem(); //ViewPager Type
if (currentPage == SlidesPagerAdapter.NUMBER_SLIDES || currentPage == 0){
previousState = currentState;
currentState = state;
if (previousState == 1 && currentState == 0){
viewPager.setCurrentItem(currentPage == 0 ? SlidesPagerAdapter.NUMBER_SLIDES : 0);
}
}
}
});
When I reach the last item, the behaviour is good. But when I come back to the first element and I try to slide again, the viewpager show me the last element.
1-> 2 -> 3 -> 4 => OK
4 -> 3 -> 2 -> 1 -> 4!!!!
Solution:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int state) {
int currentPage = viewPager.getCurrentItem(); //ViewPager Type
if (currentPage == SlidesPagerAdapter.NUMBER_SLIDES-1 || currentPage == 0){
previousState = currentState;
currentState = state;
if (previousState == 1 && currentState == 0){
viewPager.setCurrentItem(currentPage == 0 ? 0 : SlidesPagerAdapter.NUMBER_SLIDES-1);
}
}
}
});
I have a viewpager with left and right arrows. I want to hide left arrow when the first position of a ViewPager and hide right arrow when the last position of a ViewPager visible.
I have referred this solution: How to get position of first and last position of viewpager?
In my view pager I have 3 visible pages at a time. For this I have used getPageWidth to 0.33f :
But it did not work as expected for me.
My code :
vpPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == (vpPager.getAdapter().getCount())-1) {
right.setVisibility(View.INVISIBLE);
} else {
right.setVisibility(View.VISIBLE);
}
if (position == 0) {
left.setVisibility(View.INVISIBLE);
} else {
left.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
In XML I have set visibility gone for both arrows.
Any help will be appreciatable. Thank you!
To find out current page of ViewPager use ViewPager.getCurrentItem()
Here is a code sample
mViewPager.addOnPageChangeListener(new CustomViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
int currentItem = vpPager.getCurrentItem();
if (currentItem == (vpPager.getAdapter().getCount()-1)) {
right.setVisibility(View.INVISIBLE);
} else {
right.setVisibility(View.VISIBLE);
}
if (currentItem == 0) {
left.setVisibility(View.INVISIBLE);
} else {
left.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
In order to make it work, I would use onPageScrolled instead of onPageSelected since the later one is not called right after the ViewPager is initialised and you can keep the buttons visible in the xml file. It would look like this:
mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (position == 0) {
left.setVisibility(View.INVISIBLE);
} else {
left.setVisibility(View.VISIBLE);
}
if (position == adapter.getCount() - 1) {
right.setVisibility(View.INVISIBLE);
} else {
right.setVisibility(View.VISIBLE);
}
}
});
The next and previous buttons are set to work like this:
left.setOnClickListener((v) -> mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1, true));
right.setOnClickListener((v) -> mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, true));
Also, using onPageScrolled you can create a nice fade-in/fade-out animation for the buttons to stop them from appearing suddenly on the screen.
The following solution is working fine with me.
In order to know last position:
For your case, you cannot get last position '6' from onPageSelected(int position). If you got position totalNumberofPages - numberOfVisiblePagesAtATime, last page is already visible on screen.
For eg , 7-3 = 4 (If you got position 4, it means last page position 6 is already on screen.)
In order to know first position:
you cannot check in onPageChangeListener(). Because this will not call in first time launch.
You need to INVISIBLE your left arrow after viewPager setup. Then in onPageChangeListener call, VISIBLE again.
private int myImagePosition = -1; // class level variable with default value -1.
set visibility of imageView when user click on next or previous
buttons.
myImageViewViewPagerPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (myImagePosition > 0) {
myImagePosition = myImagePosition - 3;
setNextPreviousArrowVisibility();
}
myViewPagerPlanDetailBroucher.setCurrentItem(myImagePosition);
}
});
myImageViewViewPagerNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (myImagePosition < myBroucherDataArrayList.size() - 1) {
myImagePosition = myImagePosition + 3;
setNextPreviousArrowVisibility();
}
myViewPagerPlanDetailBroucher.setCurrentItem(myImagePosition);
}
});
private void setNextPreviousArrowVisibility() {
if (myImagePosition > 3) {
myImageViewViewPagerPrevious.setVisibility(View.VISIBLE);
} else {
myImageViewViewPagerPrevious.setVisibility(View.INVISIBLE);
}
if (myImagePosition > -1 && myImagePosition < myArrayList.size() - 1) {
myImageViewViewPagerNext.setVisibility(View.VISIBLE);
} else {
myImageViewViewPagerNext.setVisibility(View.INVISIBLE);
}
}
here am trying to move to the next screen at view pager last position..and its moving .but when i try to swipe back from the last position ,it moves to the next screen.i need to move to the next screeen only when view pager at last position.
#Override
public void onPageScrollStateChanged(int state) {
//viewpager swipe
lastPageChange = false;
int lastIdx = viewPager.getAdapter().getCount() - 1;
curItem = viewPager.getCurrentItem();
if (curItem==lastIdx && state==1 && lastPageChange==false ) {
lastPageChange = true;
Intent main=new Intent(Top3.this,SkipActivity.class);
startActivity(main);
finish();
} else {
lastPageChange = false;
}
}
This answer is Your viewpager when you seen last position then swipe again forward it will go to next Activity.
ViewPager.OnPageChangeListener pagerListener = new ViewPager.OnPageChangeListener() {
boolean lastPageChange = false;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int lastIdx = book_adapt.getCount() - 1;
Log.d("Testing", "pos:" + position);
if (lastPageChange && position == lastIdx){
Intent main = new Intent(Top3.this, SkipActivity.class);
startActivity(main);
finish();
}
}
#Override
public void onPageSelected(int position) {
// pgText.setCurrentItem(i/2);
viewPagerSet(position);
}
#Override
public void onPageScrollStateChanged(int state) {
int lastIdx = book_adapt.getCount() - 1;
int curItem = viewPager.getCurrentItem();
if (curItem == lastIdx /*&& lastPos==lastIdx*/ && state == 1)
lastPageChange = true;
else lastPageChange = false;
}
};
viewPager.addOnPageChangeListener(pagerListener);
Try no to remove 1 from the viewPager.getAdapter().getCount()
I suppose the following thing is happening - lets say you have 5 tabs in your viewPager. You are at the last tab. You swipe back and viewPager.getCurrentItem() will return 4. At the same time you have viewPager.getAdapter().getCount() - 1 which will return 4 again (5 tabs - 1). And the condition in your if statement will be always True, thus the new activity will be loaded.
Im having trouble figuring out how to capture a swipe event on the last page of a view pager.
Basically the requirement is that when the user is on the last page, and they try to swipe to get to the next page, the activity should close.
I've tried doing this onPageScrolled but I cant seem to differentiate a left or right swipe when in there. When on the last page, the user should still maintain the functionality to move to the previous page.
So basically the case is
When on last page
if swipe prev (do normal behaviour)
if swipe next (finish activity)
Can anyone provide any suggestions?
Thanks
Here is working solution!!
Required variables
....
private boolean isLastPageSwiped;
private int counterPageScroll;
....
Inside onPageScrolled of ViewPager
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Here 6 is last position
if (position == 6 && positionOffset == 0 && !isLastPageSwiped){
if(counterPageScroll != 0){
isLastPageSwiped=true;
//Next Activity here
}
counterPageScroll++;
}else{
counterPageScroll=0;
}
}
You should include an fake blank page to your ViewPager, when user swipes your actual last page, it comes to this fake one. When this fake one is visible finish the Activity.
You should try this way, if it does not work, I can give you an example code.
I am probably really late, but then this might help someone else down the line. I got the snippet from a question on stackoverflow, where in i am just tweaking the code a little bit.
Answer from here.
ViewPager.OnPageChangeListener pagerListener = new ViewPager.OnPageChangeListener() {
boolean lastPageChange = false;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
int lastIdx = mPgScreenAdapter.getCount() - 1;
Log.d(TAG, "pos:" + position);
if(lastPageChange && position == lastIdx) {}
}
#Override
public void onPageSelected( int i) {
pgText.setCurrentItem(i/2);
}
#Override
public void onPageScrollStateChanged(int state) {
int lastIdx = mPgScreenAdapter.getCount() - 1;
int curItem = pgScreen.getCurrentItem();
if(curItem==lastIdx && state==1){
lastPageChange = true;
// i put this here since onPageScroll gets called a couple of times.
finish();
}else {
lastPageChange = false;
}
}
};
int lastPosition;
int currentPosition;
//View pager assign
ViewPager viewPager = findViewById(R.id.viewPager);
//PageIndicatorView external https://github.com/romandanylyk
PageIndicatorView pageIndicatorView = findViewById(R.id.pageIndicatorView);
//customise pageIndicatorView design
pageIndicatorView.setAnimationType(AnimationType.THIN_WORM);
pageIndicatorView.setViewPager(viewPager);
//BannerAdapter is an custom adapter for viewpage i made.
//assign data here
BannerAdapter pagerAdapter = new BannerAdapter(this, banner, new OnClickListener() {
#Override
public void onClick() {
}
});
viewPager.setAdapter(pagerAdapter);
//listener for View Pager
//this is where process of making the infinite loop
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//assign position so that can be manipulated
currentPosition = position;
}
#Override
public void onPageSelected(int position) {
//set pager indicator position here
pageIndicatorView.setSelection(position);
}
#Override
public void onPageScrollStateChanged(int state) {
//check state 0 mean no ongoing process
if(state == 0){
//check currentPosition == lastPosition to detect that scroll cant scroll anymore
if(currentPosition == lastPosition){
int lastitem = banner.size() - 1;
//check position if either last item/first item
//and set viewpager current page as follow
if(currentPosition == lastitem){
viewPager.setCurrentItem(0);
}else if(currentPosition == 0){
viewPager.setCurrentItem(lastitem);
}
}else{
lastPosition = currentPosition;
}
Log.d("ScrollState", "currentPosition: " + currentPosition);
}
/*empty*/
}
});
I also tried my luck to find solution. Here is working code.Hope it will help someone else:-
pager.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) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
int curr = pager.getCurrentItem();
int lastReal = pager.getAdapter().getCount() - 1;
if (curr < lastReal) {
counter = 0;
} else if (curr == lastReal) {
counter++;
if (counter == 2) {
pager.setOffscreenPageLimit(0);
pager.setCurrentItem(0, false);
counter = 0;
}
}
}
}
});
pagerIndicator.setViewPager(pager);
I used counter as global variable.
Thanks!
I created an abstract listener based on the solutions here. I wanted to do something when swiping right on the last page, or left on the first page.
import android.support.v4.view.ViewPager;
abstract class PageChangeToUnavailablePageListener implements ViewPager.OnPageChangeListener {
private int finalPageIndex;
private boolean finalPageVisible = false;
private boolean firstPageVisible = true;
private int lastScrollState = 0;
abstract void onUnavailablePageChangeOnLastPage();
abstract void onUnavailablePageChangeOnFirstPage();
public PageChangeToUnavailablePageListener(int finalPageIndex) {
this.finalPageIndex = finalPageIndex;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int i) {
firstPageVisible = (i == 0);
finalPageVisible = (i == finalPageIndex);
}
#Override
public void onPageScrollStateChanged(int state) {
// The normal state sequence for changing pages is
// DRAGGING (user starts drag), SETTLING (next page is chosen), IDLE (animation is complete).
// No next page is chosen when dragging right on last page, or left on first page.
// In this case the SETTLING state is missing and the sequence is (DRAGGING, IDLE).
if (lastScrollState == ViewPager.SCROLL_STATE_DRAGGING && state == ViewPager.SCROLL_STATE_IDLE) {
// The user scrolled to an unavailable page.
if (finalPageVisible) {
onUnavailablePageChangeOnLastPage();
} else if (firstPageVisible) {
onUnavailablePageChangeOnFirstPage();
}
}
lastScrollState = state;
}
}
Hope you got an answer, i came across the same issue and this is what i did:
Incase you are using a viewpager and an activity with a class extending FragmentStatePagerAdapter you can use the getItem(int position) method to check if you reached the last page. This is also if you declared the NUM_PAGES and you can use it to detect the user has reached the last page.
in Activity:
private static int MAX_LAYOUTS = 3;
private boolean isLastPageSwiped;
private int counterPageScroll;
In onCreate:
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position == MAX_LAYOUTS - 1 && positionOffset == 0 && !isLastPageSwiped) {
if (counterPageScroll != 0) {
isLastPageSwiped = true;
Intent intent = new Intent(OldActivity.this, NewActivity.class);
startActivity(intent);
}
counterPageScroll++;
} else {
counterPageScroll = 0;
}
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
};
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
i have also solution for these(in kotlin),
Example my tabview has 3 pages.
......
private var isLastPageSwiped = false
private var indexPageScroll = 0
......
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
if (position == 2 && positionOffset == 0f && !isLastPageSwiped) {
if (indexPageScroll != 0) {
isLastPageSwiped = true
//Next Activity here
//You can perform your action on last page scroll.
}
indexPageScroll++
} else {
indexPageScroll = 0
}
}
I have a ViewPager. Now I need to add the NavigationDrawer. If the user is on the first page of the viewPager(the left-side first page) and he swipes from left to right, I need to show the Navigation Drawer. How can I achieve that? Do I have to override OnTouch listeners?
In other words I need the NavigationDrawer to appear by swiping whole scree, and not only the edge of the screen
private ViewPager.OnPageChangeListener mPageChangeListener =
new ViewPager.OnPageChangeListener() {
private int times = 0;
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
Log.d(TAG, "position:" + position
+ "\noffset: " + positionOffset
+ "\npixels: " + positionOffsetPixels);
if (position == 0 && positionOffset == 0 && positionOffsetPixels == 0) {
times++;
if (times >= 3) {
mDrawerLayout.openDrawer(mNavigationView);
}
}
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
times = 0;
}
}
};
You need to count the times of position == 0 && positionOffset == 0 && positionOffsetPixels == 0, because situation would happen when page_1 to page_0
Set a PageChangeListener on your view pager
pager = (ViewPager) findViewById(R.id.tutorial_pager);
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrolled(int position, float positionOffset,
int postitionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Then in onPageScrolled use the position == 1 and the position offset to trigger a mNavigationDrawer.openDrawer(gravity)
I think you will need to create a custom View Pager and override the onTouchEvent method to detect when you're on the first page and scrolling from left to right and make it open the navigation drawer