In my android application i have used viewpager, but i need to change the view of viewpager as like below
My Adapter
pager.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(View page, float position) {
// do transformation here
// page.setRotationY(position * -40);
final float normalizedposition = Math.abs(Math.abs(position) - 1);
page.setScaleX(normalizedposition / 2 + 0.4f);
page.setScaleY(normalizedposition / 2 + 0.4f);
}
});
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
pager.setCurrentItem(position);
}
#Override
public void onPageScrolled(int position, float positionOffset,
int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
can anyone suggest how to achieve this
All answers are most welcome
Related
I am making an android launcher and I want to make the wallpaper scroll when the page scroll so I add a onPageChangeListener to mViewPager and change the wallpaper offsets
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener(){
#Override
public void onPageScrolled(int p1, float p2, int p3) {
}
#Override
public void onPageSelected(int p1) {
WallpaperManager.getInstance(c).setWallpaperOffsets(v.getWindowToken(),(float)p1/(myPageItemsCount-1), 0);
}
#Override
public void onPageScrollStateChanged(int p1) {
}
});
The problem is that I want the wallpaper to smooth scroll when the page changed but in my above code , it will directly change the wallpaper to the corresponding position , please help.
Here's what I did and it works like a charm:
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
WallpaperManager.getInstance(getBaseContext()).setWallpaperOffsets(pager.getWindowToken(), (float) (position + positionOffset) / (myPageItemsCount-1), 0);
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
How to implement stack transformation in VerticalViewPager,Here is my code which i have implemented VerticalViewPager with stack transformation but the issue is it is fading out, I want to remove fading out while swipe up the page.
public class VerticalViewPager extends Activity {
private static final float MIN_SCALE = 0.75f;
PagerAdapter adapter;
private static final float MIN_ALPHA = 0.75f;
private boolean a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.verticalviewpager);
final fr.castorflex.android.verticalviewpager.VerticalViewPager verticalViewPager = (fr.castorflex.android.verticalviewpager.VerticalViewPager) findViewById(R.id.verticalviewpager);
adapter = new MyCustomAdapter(VerticalViewPager.this, SplashScreen.newsidArray, SplashScreen.newsdescArray, SplashScreen.newstitleArray,
SplashScreen.newsimageArray, SplashScreen.newsdateArray, SplashScreen.newsauthorArray, SplashScreen.newsurlArray);
verticalViewPager.setOffscreenPageLimit(1);
verticalViewPager.setAdapter(adapter);
verticalViewPager.setPageTransformer(false, new PageTransformer() {
#Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
view.setAlpha(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1F-position);
view.setTranslationY((int) ((float) (pageHeight) * -position));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
});
verticalViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int page = verticalViewPager.getCurrentItem();
Log.e("page",String.valueOf(page));
if((page+1)== MyCustomAdapter.nodata){
// Toast.makeText(VerticalViewPager.this,"No News Available To Swipeup",500).show();
final Toast toast = Toast.makeText(getApplicationContext(), "No News Available To Swipeup", Toast.LENGTH_SHORT);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 500);
}
}
public void onPageSelected(int position) {
SplashScreen.myCustomPosition = position;
}
});
}
}
I want to show viewpager next and before page preview in screen. Before and next page show deep in screen and slide next page with deep animation.
You can look this image
How can i do it?
Finally, i did it :) I modify this answer Android - Carousel like widget which displays a portion of the left and right elements
You can look this code.
//pager settings
pager.setClipToPadding(false);
pager.setPageMargin(24);
pager.setPadding(48, 8, 48, 8);
pager.setOffscreenPageLimit(3);
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.i("", "onPageScrolled: " + position);
CampaignPagerFragment sampleFragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(position);
float scale = 1 - (positionOffset * RATIO_SCALE);
// Just a shortcut to findViewById(R.id.image).setScale(scale);
sampleFragment.scaleImage(scale);
if (position + 1 < pager.getAdapter().getCount()) {
sampleFragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(position + 1);
scale = positionOffset * RATIO_SCALE + (1 - RATIO_SCALE);
sampleFragment.scaleImage(scale);
}
}
#Override
public void onPageSelected(int position) {
Log.i("", "onPageSelected: " + position);
}
#Override
public void onPageScrollStateChanged(int state) {
Log.i("", "onPageScrollStateChanged: " + state);
if (state == ViewPager.SCROLL_STATE_IDLE) {
CampaignPagerFragment fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem());
fragment.scaleImage(1);
if (pager.getCurrentItem() > 0) {
fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem() - 1);
fragment.scaleImage(1 - RATIO_SCALE);
}
if (pager.getCurrentItem() + 1 < pager.getAdapter().getCount()) {
fragment = (CampaignPagerFragment) ((CampaignPagerAdapter) pager.getAdapter()).getRegisteredFragment(pager.getCurrentItem() + 1);
fragment.scaleImage(1 - RATIO_SCALE);
}
}
}
});
//PagerAdapter
public class CampaignPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public CampaignPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 5;
}
#Override
public Fragment getItem(int position) {
return new CampaignPagerFragment();
}
#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);
}
}
for ex: https://github.com/mrleolink/SimpleInfiniteCarousel..
Hello, One thing that is missing
sampleFragment.scaleImage(scale);
It is a method created in CampaignPagerFragment and it scale the fragment rootView..
e.g public void scaleImage(float scaleX)
{
rootView.setScaleY(scaleX);
rootView.invalidate();
}
You can use PagerTransformer to ViewPager :-
mViewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(View page, float position) {
// do transformation here
}
});
Use this link for complete tutorial :-
http://andraskindler.com/blog/2013/create-viewpager-transitions-a-pagertransformer-example/
Hope this help you :)
viewPager.setPageMargin(100);
viewPager.setPageTransformer(false, new ViewPager.PageTransformer()
{
#Override
public void transformPage(View page, float position)
{
int pageWidth = viewPager.getMeasuredWidth() -
viewPager.getPaddingLeft() - viewPager.getPaddingRight();
int pageHeight = viewPager.getHeight();
int paddingLeft = viewPager.getPaddingLeft();
float transformPos = (float) (page.getLeft() -
(viewPager.getScrollX() + paddingLeft)) / pageWidth;
int max = pageHeight / 10;
if (transformPos < -1)
{
// [-Infinity,-1)
// This page is way off-screen to the left.
page.setAlpha(0.5f);// to make left transparent
page.setScaleY(0.7f);
}
else if (transformPos <= 1)
{
// [-1,1]
page.setScaleY(1f);
}
else
{
// (1,+Infinity]
// This page is way off-screen to the right.
page.setAlpha(0.5f);// to make right transparent
page.setScaleY(0.7f);
}
}
});
I think this is the simplest and cleanest solution.
float scaleFactor = 0.85f;
viewPager.setPageMargin(-35);
viewPager.setOffscreenPageLimit(2);
viewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
page.setScaleY((1 - Math.abs(position) * (1 - scaleFactor)));
page.setScaleX(scaleFactor + Math.abs(position) * (1 - scaleFactor));
}
});
I did this by changing my viewpager's padding based on the position.
carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, 12), 0, Utils.dpToPixels(context, paddingRequired - 12), 0); // initial padding for position 0
carouselViewHolder.carouselViewPager.setPageMargin(Utils.dpToPixels(context, 12)); // margin between pages
carouselViewHolder.carouselViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position != 0) {
if (position == playCardData.getPlayCards().size() - 1) {
carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, finalPaddingRequired - 12), 0, Utils.dpToPixels(context, 12), 0);
} else
carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, finalPaddingRequired / 2), 0, Utils.dpToPixels(context, finalPaddingRequired / 2), 0);
} else {
carouselViewHolder.carouselViewPager.setPadding(Utils.dpToPixels(context, 12), 0, Utils.dpToPixels(context, finalPaddingRequired - 12), 0);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
im used this libarary https://github.com/47deg/android-swipelistview
in project im want row only swipe to left and not allow swipe rows
with wiche other and when clicked row not swipeing and open new Activity
public class Aragh extends Activity {
SwipeListView swipelistview;
ItemAdapter adapter;
List<ItemRow> itemData;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aragh);
swipelistview=(SwipeListView)findViewById(R.id.example_swipe_lv_list);
itemData=new ArrayList<ItemRow>();
adapter=new ItemAdapter(this,R.layout.custom_row,itemData);
swipelistview.setSwipeListViewListener(new BaseSwipeListViewListener() {
#Override
public void onOpened(int position, boolean toRight) {
}
#Override
public void onClosed(int position, boolean fromRight) {
}
#Override
public void onListChanged() {
}
#Override
public void onMove(int position, float x) {
}
#Override
public void onStartOpen(int position, int action, boolean right) {
Log.d("swipe", String.format("onStartOpen %d - action %d", position, action));
}
#Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
}
#Override
public void onClickFrontView(int position) {
Log.d("swipe", String.format("onClickFrontView %d", position));
swipelistview.openAnimate(position); //when you touch front view it will open
}
#Override
public void onClickBackView(int position) {
Log.d("swipe", String.format("onClickBackView %d", position));
swipelistview.closeAnimate(position);//when you touch back view it will close
}
#Override
public void onDismiss(int[] reverseSortedPositions) {
}
});
//These are the swipe listview settings. you can change these
//setting as your requirement
swipelistview.setSwipeMode(SwipeListView.SWIPE_MODE_RIGHT); // there are five swiping modes
swipelistview.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_DISMISS); //there are four swipe actions
swipelistview.setSwipeActionRight(SwipeListView.SWIPE_ACTION_DISMISS);
swipelistview.setOffsetLeft(convertDpToPixel(0f)); // left side offset
swipelistview.setOffsetRight(convertDpToPixel(80f)); // right side offset
swipelistview.setAnimationTime(500); // Animation time
swipelistview.setSwipeOpenOnLongPress(false); // enable or disable SwipeOpenOnLongPress
swipelistview.setAdapter(adapter);
for(int i=0;i<10;i++)
{
itemData.add(new ItemRow("Swipe Item"+i,getResources().getDrawable(R.drawable.ic_launcher) ));
}
adapter.notifyDataSetChanged();
}
public int convertDpToPixel(float dp) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return (int) px;
}
}
I recommend doing it in XML.
in your SwipeListView tag add
swipe:swipeMode="left"
it locks your swipe mode to the left.
you can choose - left / right / both .
You just need to put swipe:swipeMode="left" inside <....SwipeListView /> in your xml layout to allow swiping only in left direction
I'm trying to synchronize two ViewPagers, as apparently have quite a lot of people before me, and I've got as far as this:
private ViewPager mNavPager;
private ViewPager mMainPager;
private final OnPageChangeListener mNavPagerListener = new OnPageChangeListener() {
private boolean mNavDragging;
private int mScrollPosition;
#Override
public void onPageSelected(int position) {
mScrollPosition = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(mNavDragging)
mMainPager.scrollTo(positionOffsetPixels, 0);
}
#Override
public void onPageScrollStateChanged(int state) {
switch(state) {
case ViewPager.SCROLL_STATE_DRAGGING:
case ViewPager.SCROLL_STATE_SETTLING:
mNavDragging = true;
break;
case ViewPager.SCROLL_STATE_IDLE:
mNavDragging = false;
break;
}
}
};
private OnPageChangeListener mMainPagerListener = new OnPageChangeListener() {
private boolean mMainDragging;
private int mScrollPosition;
#Override
public void onPageSelected(int position) {
mScrollPosition = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(mMainDragging)
mNavPager.scrollTo(positionOffsetPixels, 0);
}
#Override
public void onPageScrollStateChanged(int state) {
switch(state) {
case ViewPager.SCROLL_STATE_DRAGGING:
case ViewPager.SCROLL_STATE_SETTLING:
mMainDragging = true;
break;
case ViewPager.SCROLL_STATE_IDLE:
mMainDragging = false;
break;
}
}
};
If either one is scrolled manually, the other is slaved to it using the scroll state property. It works beautifully till the items reach their final position; at this point, the slaved pager flicks instantly back to the previously selected item, as though the scrolling hadn't taken place.
I have tried calling ViewPager#setCurrentItem(mScrolledPosition) with a variety of different logic constraints but that doesn't work either, though it does occasionally make it worse. I feel as though there must be something that can be done with that but I'm not sure what.
How can I get the slaved pager to remain in the correct position?
I solved this problem in a much easier (and cleaner) way using the OnPageChangeListener:
mViewPager1.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private int mScrollState = ViewPager.SCROLL_STATE_IDLE;
#Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
return;
}
mViewPager2.scrollTo(mViewPager1.getScrollX(), mViewPager2.getScrollY());
}
#Override
public void onPageSelected(final int position) {
}
#Override
public void onPageScrollStateChanged(final int state) {
mScrollState = state;
if (state == ViewPager.SCROLL_STATE_IDLE) {
mViewPager2.setCurrentItem(mViewPager1.getCurrentItem(), false);
}
}
});
mViewPager2.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private int mScrollState = ViewPager.SCROLL_STATE_IDLE;
#Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
return;
}
mViewPager1.scrollTo(mViewPager2.getScrollX(), mViewPager1.getScrollY());
}
#Override
public void onPageSelected(final int position) {
}
#Override
public void onPageScrollStateChanged(final int state) {
mScrollState = state;
if (state == ViewPager.SCROLL_STATE_IDLE) {
mViewPager1.setCurrentItem(mViewPager2.getCurrentItem(), false);
}
}
});
I have Solved the problem without utilizing the Listener.
So you can use the listener for some other stuff and will make code look cleaner.
I know its a question asked a long ago. I was searching for a solution and solved it myself.
This is how my Custom ViewPager code is
public class CustomPager extends ViewPager {
CustomPager mCustomPager;
private boolean forSuper;
public CustomPager(Context context) {
super(context);
}
public CustomPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
if (!forSuper) {
mCustomPager.forSuper(true);
mCustomPager.onInterceptTouchEvent(arg0);
mCustomPager.forSuper(false);
}
return super.onInterceptTouchEvent(arg0);
}
#Override
public boolean onTouchEvent(MotionEvent arg0) {
if (!forSuper) {
mCustomPager.forSuper(true);
mCustomPager.onTouchEvent(arg0);
mCustomPager.forSuper(false);
}
return super.onTouchEvent(arg0);
}
public void setViewPager(CustomPager customPager) {
mCustomPager = customPager;
}
public void forSuper(boolean forSuper) {
this.forSuper = forSuper;
}
#Override
public void setCurrentItem(int item, boolean smoothScroll) {
if (!forSuper) {
mCustomPager.forSuper(true);
mCustomPager.setCurrentItem(item, smoothScroll);
mCustomPager.forSuper(false);
}
super.setCurrentItem(item, smoothScroll);
}
#Override
public void setCurrentItem(int item) {
if (!forSuper) {
mCustomPager.forSuper(true);
mCustomPager.setCurrentItem(item);
mCustomPager.forSuper(false);
}
super.setCurrentItem(item);
}
}
And you have to set pagers like this before adapter is set and just after getting reference using the ID.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
backPager=(CustomPager) findViewById(R.id.BackPager);
frontPager = (CustomPager) findViewById(R.id.frontPager);
frontPager.setViewPager(backPager);
backPager.setViewPager(frontPager);
backPager.setAdapter(your Adapter);
frontPager.setAdapter(your Adapter);
}
Must set ViewPagers before assigning adapter.
I had a similar issue, also needed to combine my syncing with animations in PageTransformer.
Originally posted this answer here: https://stackoverflow.com/a/43638796/2867886
But I will paste it here for convenience.
The solution that worked best for me was to pass MotionEvent in OnTouchListener between ViewPager instances. Tried fake dragging but it was always laggy and buggy - I needed a smooth, parallax-like effect.
So, my advice is to implement a View.OnTouchListener. The MotionEvent has to be scaled to compensate for the difference in width.
public class SyncScrollOnTouchListener implements View.OnTouchListener {
private final View syncedView;
public SyncScrollOnTouchListener(#NonNull View syncedView) {
this.syncedView = syncedView;
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
MotionEvent syncEvent = MotionEvent.obtain(motionEvent);
float width1 = view.getWidth();
float width2 = syncedView.getWidth();
//sync motion of two view pagers by simulating a touch event
//offset by its X position, and scaled by width ratio
syncEvent.setLocation(syncedView.getX() + motionEvent.getX() * width2 / width1,
motionEvent.getY());
syncedView.onTouchEvent(syncEvent);
return false;
}
}
Then set it to your ViewPager
sourcePager.setOnTouchListener(new SyncScrollOnTouchListener(targetPager));
Note that this solution will only work if both pagers have the same orientation. If you need it to work for different orientations - adjust syncEvent Y coordinate instead of X.
There is one more issue that we need to take into account - minimum fling speed and distance that can cause just one pager to change page.
It can be easily fixed by adding an OnPageChangeListener to our pager
sourcePager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
//no-op
}
#Override
public void onPageSelected(int position) {
targetPager.setCurrentItem(position, true);
}
#Override
public void onPageScrollStateChanged(int state) {
//no-op
}
});
This does everything right except it sometimes misses very quick flicks on the slaved view. For some reason including fake drag events during the settling phase causes real problems, though.
private ViewPager mNavPager;
private ViewPager mMainPager;
private final OnPageChangeListener mNavPagerListener = new OnPageChangeListener() {
private int mLastScrollPosition;
private int mLastPagePosition;
#Override
public void onPageSelected(int position) {
mLastPagePosition = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(mMainPager.isFakeDragging()) {
int absoluteOffsetPixels = positionOffsetPixels;
if(mLastPagePosition!=position) {
absoluteOffsetPixels += (position - mLastPagePosition) * mMainPager.getWidth();
mLastPagePosition = position;
}
Log.d(TAG, "fake nav drag by " + (mLastScrollPosition - absoluteOffsetPixels));
mMainPager.fakeDragBy(mLastScrollPosition - absoluteOffsetPixels);
mLastScrollPosition = positionOffsetPixels;
}
}
#Override
public void onPageScrollStateChanged(int state) {
if(!mNavPager.isFakeDragging()) {
switch(state) {
case ViewPager.SCROLL_STATE_DRAGGING:
if(!mMainPager.isFakeDragging())
mMainPager.beginFakeDrag();
break;
case ViewPager.SCROLL_STATE_SETTLING:
case ViewPager.SCROLL_STATE_IDLE:
if(mMainPager.isFakeDragging()) {
mMainPager.endFakeDrag();
mLastScrollPosition = 0;
}
break;
}
}
}
};
private OnPageChangeListener mMainPagerListener = new OnPageChangeListener() {
private int mLastScrollPosition;
private int mLastPagePosition;
#Override
public void onPageSelected(int position) {
mLastPagePosition = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(mNavPager.isFakeDragging()) {
int absoluteOffsetPixels = positionOffsetPixels;
if(mLastPagePosition!=position) {
absoluteOffsetPixels += (position - mLastPagePosition) * mMainPager.getWidth();
mLastPagePosition = position;
}
Log.d(TAG, "fake nav drag by " + (mLastScrollPosition - absoluteOffsetPixels));
mNavPager.fakeDragBy(mLastScrollPosition - absoluteOffsetPixels);
mLastScrollPosition = positionOffsetPixels;
}
}
#Override
public void onPageScrollStateChanged(int state) {
if(!mMainPager.isFakeDragging()) {
switch(state) {
case ViewPager.SCROLL_STATE_DRAGGING:
if(!mNavPager.isFakeDragging())
mNavPager.beginFakeDrag();
break;
case ViewPager.SCROLL_STATE_SETTLING:
case ViewPager.SCROLL_STATE_IDLE:
if(mNavPager.isFakeDragging()) {
mNavPager.endFakeDrag();
mLastScrollPosition = 0;
}
break;
}
}
}
};
EDIT
I now believe this to be impossible without some fairly substantial custom code. The reason is essentially that both ViewPagers have a VelocityTracker inside, which controls scrolling. Since the MotionEvents being passed in may not be passed to the VelocityTracker at the same relative times for each pager, the trackers will occasionally reach different conclusions about how to react.
However, it is possible to use a modified PagerTitleStrip to get precise tracking of a ViewPager, and to transfer touch events captured by the strip directly to the ViewPager.
The source for PagerTitleStrip is here.
Broadly, what needs to be done to make this work is as follows: replace mPrevText, mCurrText and mNextText with views of the type you want to use; remove the onAttachedToWindow() and onDetachedFromWindow() functions; remove calls to the PagerAdapter that deal with dataset observers, and add an OnTouchListener to the modified strip that fake drags the main pager. You'll also need to add the modified title strip as an OnPageChangeListener to the ViewPager since the internal listeners aren't visible outside the package.
Is this a gigantic pain? Yes. But it works. I will write it up in more detail soon.
With help from all other answers I've created a Class so it easily can be implemented.
public class OnPageChangeListernerSync implements ViewPager.OnPageChangeListener {
private ViewPager master;
private ViewPager slave;
private int mScrollState = ViewPager.SCROLL_STATE_IDLE;
public OnPageChangeListernerSync(ViewPager master, ViewPager slave){
this.master = master;
this.slave = slave;
}
#Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
return;
}
this.slave.scrollTo(this.master.getScrollX()*
this.slave.getWidth()/
this.master.getWidth(), 0);
}
#Override
public void onPageSelected(final int position) {
}
#Override
public void onPageScrollStateChanged(final int state) {
mScrollState = state;
if (state == ViewPager.SCROLL_STATE_IDLE) {
this.slave.setCurrentItem(this.master
.getCurrentItem(), false);
}
}
}
...
// In your activity
this.upperPager.addOnPageChangeListener(new OnPageChangeListernerSync(this.upperPager, this.lowerPager));
this.lowerPager.addOnPageChangeListener(new OnPageChangeListernerSync(this.lowerPager, this.upperPager));
All the Answers are approximately currect in some situation. Here I am giving one more answer which will use to slide both the ViewPagers simultaneously whether there size is same or not:
viewPagerBanner.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private int scrollState = ViewPager.SCROLL_STATE_IDLE;
// Indicates that the pager is in an idle, settled state.
// The current page is fully in view and no animation is in progress.
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (scrollState == ViewPager.SCROLL_STATE_IDLE) {
return;
}
viewPagerTitle.scrollTo(viewPagerBanner.getScrollX()*
viewPagerTitle.getWidth()/
viewPagerBanner.getWidth(), 0);
// We are not interested in Y axis position
}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {
scrollState = state;
if (state == ViewPager.SCROLL_STATE_IDLE) {
viewPagerTitle.setCurrentItem(viewPagerBanner.getCurrentItem(), false);
}
}
});