ViewPager setCurrentItem (pageId, true) DOES NOT float

I compile on SDK 4.03, Samsung Infuse Android 2.2, the support library for Android 4 and using ViewPager in my application, the actual swipe works fine, but when I do

viewPager.setCurrentItem(id); // , or viewPager.setCurrentItem(id, true); 

It does not smooth scrolling, but instantly switches views. Although the documentation clearly states that this is the goal of setting the second argument to true. What's up with that?

+45
android android-layout
Aug 14 '12 at 23:25
source share
11 answers

I fixed this by creating a MyViewPager that overrides ViewPager.mScroller using reflection.

 public class MyViewPager extends ViewPager { public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); setMyScroller(); } private void setMyScroller() { try { Class<?> viewpager = ViewPager.class; Field scroller = viewpager.getDeclaredField("mScroller"); scroller.setAccessible(true); scroller.set(this, new MyScroller(getContext())); } catch (Exception e) { e.printStackTrace(); } } public class MyScroller extends Scroller { public MyScroller(Context context) { super(context, new DecelerateInterpolator()); } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, 1000 /*1 secs*/); } } } 
+42
Mar 21 '13 at 14:07
source share

This is what I did. I overridden the private-private smoothScrollTo in ViewPager , putting my own subclass in the same package. A value of zero was passed to it, which leads to binding behavior instead of smooth scrolling.

 package android.support.v4.view; import android.content.Context; import android.util.AttributeSet; public class MyViewPager extends ViewPager { public MyViewPager(Context context) { super(context); } public MyViewPager(Context context, AttributeSet attr) { super(context, attr); } void smoothScrollTo(int x, int y, int velocity) { super.smoothScrollTo(x, y, 1); } } 

It did a great job if you want you to be able to calculate and ensure the actual ISO speed in just 1.

+16
Feb 08 '13 at 15:45
source share

I called the setCurrentItem function in the handler, and it worked fine for me.

 new Handler().post(new Runnable() { @Override public void run() { myViewPager.setCurrentItem(1, true); } }); 

Hope this helps.

+9
Nov 02 '15 at 9:06
source share

I know this thread is pretty old, but this is one of the best results from Google. I have come back many times to solve this problem. None of the solutions above helped me at all. However, I found a solution that works for me.

Currently my setup looks like a view from inside the viewpager. When you click on one of the views, it creates a new page and scrolls it. It was very fast, but it seems that this is because I called

 mViewPager.setCurrentItem(intIndex, true); 

from within my OnClickEvent. For some reason, the viewpager doesn't like it, so instead I made this function. It creates a new thread that runs runnable in the user interface thread. This runnable is what tells ViewPager to scroll to a specific element.

 public static void scrollToIndex(int index) { final int intIndex = index; //We're going to make another thread to separate ourselves from whatever //thread we are in Thread sepThread = new Thread(new Runnable(){ public void run() { //Then, inside that thread, run a runnable on the ui thread. //MyActivity.getContext() is a static function that returns the //context of the activity. It useful in a pinch. ((Activity)MyActivity.getContext()).runOnUiThread(new Runnable(){ @Override public void run() { if (mSlidingTabLayout != null) { //I'm using a tabstrip with this as well, make sure //the tabstrip is updated, or else it won't scroll //correctly if(mSlidingTabLayout.getTabStripChildCount() <= intIndex) mSlidingTabLayout.updateTabStrip(); //Inside this thread is where you call setCurrentItem mViewPager.setCurrentItem(intIndex, true); } } }); } }); sepThread.start(); } 

Hope I at least helped someone with this problem. Good luck

Edit: Looking back at my answer, I'm sure you can just run ui on the thread, and it should work. Take it with salt, although I have not tested it yet.

+6
Jun 19 '15 at 15:39
source share

ViewPager has changed a lot from 5 to 9. Some of these changes may be related to your problem:

  • Bugs for user interface behavior in ViewPager (versions 5 and 6) have been fixed.
  • Many bugs fixed for ViewPager (version 9)

By making it clear that your code should work fine, I suggest that your support library is not updated. Try updating the library if it is not.

+1
Aug 15 2018-12-12T00: 00Z
source share

I created this class because I was not completely satisfied with the above solutions

The class overrides setCurrentItem(int item, boolean smoothScroll) and uses reflection to keep this method as original as possible. The key point is that the speed is not 0. You only need to replace the current ViewPager with this MyViewPager class and use it as usual:

 import android.content.Context; import android.util.AttributeSet; import java.lang.reflect.Field; import java.lang.reflect.Method; import androidx.viewpager.widget.ViewPager; public class MyViewPager extends ViewPager { public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); } /** * Set the currently selected page. If the ViewPager has already been through its first * layout with its current adapter there will be a smooth animated transition between * the current item and the specified item. * * @param item Item index to select * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately */ @Override public void setCurrentItem(int item, boolean smoothScroll) { final Class<?> viewpager = ViewPager.class; int velocity = 1; try { Field mPopulatePending = viewpager.getDeclaredField("mPopulatePending"); mPopulatePending.setAccessible(true); mPopulatePending.set(this, false); Method setCurrentItemInternal = viewpager.getDeclaredMethod("setCurrentItemInternal", int.class, boolean.class, boolean.class, int.class); setCurrentItemInternal.setAccessible(true); setCurrentItemInternal.invoke(this, item, smoothScroll, false, velocity); } catch (Exception e) { e.printStackTrace(); } } } 
+1
Nov 05 '18 at 15:47
source share

I had the same problem, but today I found a simple solution. Maybe this will help you. First, let's assume that we have a ViewPager that fills the entire screen. To switch between pages, I created my own custom tabbed view and placed it on top of the ViewPager. A click on a tab should smoothly scroll to the corresponding page in the ViewPager using setCurrentItem (item, true) - but it scrolls instantly, without any smoothness! Then I tried to add a simple button (not a custom one) through the ViewPager + callback:

 @Override public void onClick(View v) { viewPager.setCurrentItem(item, true); } 

After that, a smooth scroll looked at the work. So, the solution was very simple: inside the Button class, the internal Boolean onTouch (...) listener returns true, so it will always DEMAND touch events! Then smooth scrolling started working for my custom tab view when I replaced "return false" with "return true" in the internal boolean onTouch (...) listener.

I hope my success story helps you.

0
Aug 16 2018-12-12T00: 00Z
source share

For those using Xamarin (although this approach also applies to Java), I can suggest using the following approach based on the answer above (ViewPager from Android Support Library v7 AppCompat 19.1.0):

 public void ScrollSmooth(int i) { var jClass = JNIEnv.GetObjectClass(_pager.Handle); var jMethod = JNIEnv.GetMethodID(jClass, "setCurrentItemInternal", "(IZZI)V"); JNIEnv.CallVoidMethod (_pager.Handle, jMethod, new JValue (i), new JValue (true), new JValue (false), new JValue (1)); } 

It relies on the implementation of ViewPager from http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/support/v4/view/ViewPager.java

0
Jul 25 '14 at 0:57
source share

Having spent my whole day, I found a solution with offscreenPageLimit installed on a total of no. pages.

please follow this

0
Feb 21 '19 at 6:02
source share

Pay attention to this variable mFirstLayout - it will be set to true if the onAttachedToWindow viewpager for the onAttachedToWindow (for example, in the resellerโ€™s overview) onAttachedToWindow is not onAttachedToWindow so there will be no smoothScroll. You must override onAttachedToWindow to control the mFirstLayout variable. Something like that:

  @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); try { Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout"); mFirstLayout.setAccessible(true); mFirstLayout.set(this, false); getAdapter().notifyDataSetChanged(); setCurrentItem(getCurrentItem()); } catch (Exception e) { e.printStackTrace(); } } 
0
May 05 '19 at 3:48
source share

try this code:

 viewPager.postDelayed(new Runnable() { @Override public void run() { viewPager.setCurrentItem(id, true); } }, 100); 
-5
Sep 15 '16 at 21:40
source share



All Articles