Android ViewPager infinite loop sliding and automatic scrolling complete example

  • 2021-08-28 21:16:37
  • OfStack

For ViewPager advertising page this function a lot of APP have this function on the Internet have also seen some information, I will be in this complete implementation of my own method to write it out

Basic ViewPager:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/top_item"
  android:orientation="vertical">

    <android.support.v4.view.ViewPager
      android:layout_width="match_parent"
      android:layout_height="180dp"
      android:id="@+id/top_vp"

      ></android.support.v4.view.ViewPager>

</LinearLayout>

It's very simple. It's just an ViewPager

Next, add ImageView to Adapter of ViewPager under simple setting 1


public class MainActivity extends AppCompatActivity {

  private ViewPager topVp;
  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; // Simulate storing the picture to be displayed 
  private List<ImageView> imageViews ;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initImageViews();
    initVp();
  }

  /**
   *  Initialize picture resources 
   */
  private void initImageViews() {
    imageViews = new ArrayList<>();
    for(int i = 0;i<images.length;i++){
      ImageView imageView = new ImageView(this);
      imageView.setScaleType(ImageView.ScaleType.FIT_XY);
      imageView.setImageResource(images[i]);
      imageViews.add(imageView);
    }
  }

  private void initVp() {

    topVp = (ViewPager) findViewById(R.id.top_vp);
    topVp.setAdapter(new PagerAdapter() {
      @Override
      public int getCount() {
        return imageViews.size();
      }

      @Override
      public boolean isViewFromObject(View view, Object object) {
        return view==object;
      }

      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(imageViews.get(position));
      }

      @Override
      public Object instantiateItem(ViewGroup container, int position) {
        container.addView(imageViews.get(position));
        return imageViews.get(position);
      }
    });
  }

}

The above is the most basic ViewPager. Below, we can transform it on this basis

Achieve infinite circular sliding:

Here I prior loop sliding way is very simple is to set adapter count to a very large value so that it can not slide to the head and then switch pictures can be achieved although the method is compared with LOW but the effect is still OK

The code is modified under the basic ViewPager as follows:


public class MainActivity extends AppCompatActivity {

  private ViewPager topVp;
  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; // Simulate storing the picture to be displayed 
  private List<ImageView> imageViews ;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initImageViews();
    initVp();
  }

  /**
   *  Initialize picture resources 
   */
  private void initImageViews() {
    imageViews = new ArrayList<>();
    for(int i = 0;i<images.length;i++){
      ImageView imageView = new ImageView(this);
      imageView.setScaleType(ImageView.ScaleType.FIT_XY);
      imageView.setImageResource(images[i]);
      imageViews.add(imageView);
    }
  }

  private void initVp() {

    topVp = (ViewPager) findViewById(R.id.top_vp);
    topVp.setAdapter(new PagerAdapter() {
      @Override
      public int getCount() {
//        return imageViews.size();  Amend as follows 
        return 10000;
      }

      @Override
      public boolean isViewFromObject(View view, Object object) {
        return view==object;
      }

      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
//        container.removeView(imageViews.get(position%imageViews.size()));  Delete this sentence   This sentence is not deleted   Will appear   Sliding   The situation where the layout disappears   Because it was removed   This modification here will affect 1 Some performance. . . . . 
      }

      @Override
      public Object instantiateItem(ViewGroup container, int position) {
//        container.addView(imageViews.get(position));
//        return imageViews.get(position);  Amend as follows 
        try {
          container.addView(imageViews.get(position%imageViews.size()));
        }catch (Exception e){

        }
        return imageViews.get(position%imageViews.size());
      }
    });
  }

}

In this way, the infinite loop can be realized to slide right, but it is impossible to slide left when the program is just started. It is very simple to solve it only at the beginning

viewPager.setCurrentItem(1000*imageViews.size());

You can realize infinite left and right sliding in this way

Automatic timing cycle sliding:

Add the function of automatic timing sliding left and right below

The most important thing to realize automatic sliding is to realize timer function. I use Handler+Runnable method here to modify the following on the basis of the above code:


 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initImageViews();
    initVp();
    handler = new Handler();
    handler.postDelayed(new TimerRunnable(),5000);
  }

  class TimerRunnable implements Runnable{

    @Override
    public void run() {
      int curItem = topVp.getCurrentItem();
      topVp.setCurrentItem(curItem+1);
      if (handler!=null){
        handler.postDelayed(this,5000);
      }
    }
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    handler = null; // Here in Activity Timely when exiting   Recycle 
  }

After that, automatic sliding can be realized

Add a small round button in the lower left corner:

Next, add the navigation origin in the lower left corner

First modify the layout:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/top_item"
  android:orientation="vertical">
  <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="180dp">


    <android.support.v4.view.ViewPager
      android:layout_width="match_parent"
      android:layout_height="180dp"
      android:id="@+id/top_vp"

      ></android.support.v4.view.ViewPager>
    <LinearLayout
      android:id="@+id/lin_points"
      android:layout_marginBottom="10dp"
      android:layout_marginLeft="10dp"
      android:layout_alignParentBottom="true"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="horizontal"
      >

    </LinearLayout>
  </RelativeLayout>


</LinearLayout>

The origin we need to be in the LinearLayout layout

The main principle is to dynamically add small dots to this LinearLayout


public class MainActivity extends AppCompatActivity {

  private ViewPager topVp;
  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; // Simulate storing the picture to be displayed 
  private List<ImageView> imageViews ;
  private List<TextView> txtPoints;
  private LinearLayout lin_points;
  private Handler handler;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    lin_points = (LinearLayout) findViewById(R.id.lin_points);
    initImageViews();
    initVp();

    initCircle();
    /*
     *  Timer 
     */
    handler = new Handler();
    handler.postDelayed(new TimerRunnable(),5000);
  }

  /**
   *  Initialize dot 
   */
  private void initCircle() {
    txtPoints = new ArrayList<>();
    int d = 20;
    int m = 7;
    for (int i = 0; i < imageViews.size(); i++) {
      TextView txt = new TextView(this);
      if (i == 0) {
        txt.setBackgroundResource(R.drawable.point_pink);
      } else {
        txt.setBackgroundResource(R.drawable.point_grey);
      }
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(d, d);

      params.setMargins(m, m, m, m);
      txt.setLayoutParams(params);
      txtPoints.add(txt);
      lin_points.addView(txt);
    }
  }

  class TimerRunnable implements Runnable{

    @Override
    public void run() {
      int curItem = topVp.getCurrentItem();
      topVp.setCurrentItem(curItem+1);
      changePoints((curItem+1)%imageViews.size());
      if (handler!=null){
        handler.postDelayed(this,5000);
      }
    }
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    handler = null;
  }

  /**
   *  Initialize picture resources 
   */
  private void initImageViews() {
    imageViews = new ArrayList<>();
    for(int i = 0;i<images.length;i++){
      ImageView imageView = new ImageView(this);
      imageView.setScaleType(ImageView.ScaleType.FIT_XY);
      imageView.setImageResource(images[i]);
      imageViews.add(imageView);
    }
  }


  private void initVp() {

    topVp = (ViewPager) findViewById(R.id.top_vp);
    topVp.setAdapter(new PagerAdapter() {
      @Override
      public int getCount() {
//        return imageViews.size();  Amend as follows 
        return 10000;
      }

      @Override
      public boolean isViewFromObject(View view, Object object) {
        return view==object;
      }

      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
//        container.removeView(imageViews.get(position%imageViews.size()));  Delete this sentence 
      }

      @Override
      public Object instantiateItem(ViewGroup container, int position) {
//        container.addView(imageViews.get(position));
//        return imageViews.get(position);  Amend as follows 
        try {
          container.addView(imageViews.get(position%imageViews.size()));
        }catch (Exception e){

        }
        return imageViews.get(position%imageViews.size());
      }
    });

    topVp.setCurrentItem(imageViews.size()*1000);

    topVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

      }

      @Override
      public void onPageSelected(int position) {
        changePoints((position)%imageViews.size());
      }

      @Override
      public void onPageScrollStateChanged(int state) {

      }
    });
  }
  public void changePoints(int pos) {
    if (txtPoints != null) {
      for (int i = 0; i < txtPoints.size(); i++) {
        if (pos == i) {
          txtPoints.get(i).setBackgroundResource(R.drawable.point_pink);
        } else {
          txtPoints.get(i).setBackgroundResource(R.drawable.point_grey);
        }
      }
    }
  }
}

Add switching animation to ViewPager:

topVp.setPageTransformer(true,new CubeOutTransformer());

Calling this line of code can add that the following TransFormer class is a custom transition effect class

Control the speed of ViewPager automatic switching

The switching speed of ViewPager itself is written dead, We can not modify, but we can see through the source code, ViewPager switching speed is through Scroller class control, and Scroller class can be set transition time, so we can create our own Scroller class inheritance Scroller and then through the reflection of ViewPager in the ViewPager attribute set to our own can set the time of Scroller class

Here's the code:


public class FixedSpeedScroller extends Scroller {
  private int mDuration = 1500;

  public FixedSpeedScroller(Context context) {
    super(context);
  }

  public FixedSpeedScroller(Context context, Interpolator interpolator) {
    super(context, interpolator);
  }

  @Override
  public void startScroll(int startX, int startY, int dx, int dy, int duration) {
    // Ignore received duration, use fixed one instead
    super.startScroll(startX, startY, dx, dy, mDuration);
  }

  @Override
  public void startScroll(int startX, int startY, int dx, int dy) {
    // Ignore received duration, use fixed one instead
    super.startScroll(startX, startY, dx, dy, mDuration);
  }

  public void setmDuration(int time) {
    mDuration = time;
  }

  public int getmDuration() {
    return mDuration;
  }
}

Reflection modifies ViewPager properties:


 try {
      Field field = ViewPager.class.getDeclaredField("mScroller");
      field.setAccessible(true);
      scroller = new FixedSpeedScroller(getActivity());
      scroller.setmDuration(1000);
      field.set(topVp, scroller);
    } catch (Exception e) {
//      e.printStackTrace();
      System.out.println("aaaaaa Wrong ");
    }

So you can control the speed

Ok, Android ViewPager advertisement page can slide infinitely and automatically scroll with the function of small dots is basically realized, the specific parameters can be set by yourself


Related articles: