欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android ViewPager无限循环滑动并可自动滚动完整实例

程序员文章站 2022-03-04 09:19:14
对于ViewPager 广告页这个功能很多APP都有这个功能在网上也看过一些资料,我就在这把我自己完整的实现方法写出来吧基础的ViewPager:123456789101112131415

对于ViewPager 广告页这个功能很多APP都有这个功能在网上也看过一些资料,我就在这把我自己完整的实现方法写出来吧

基础的ViewPager:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<?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>

很简单 仅仅是一个ViewPager 

接下来简单的设置一下ViewPager的Adapter 添加ImageView

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

public class MainActivity extends AppCompatActivity {

 

  private ViewPager topVp;

  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模拟存放要展示的图片

  private List<ImageView> imageViews ;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    initImageViews();

    initVp();

  }

 

  /**

   * 初始化图片资源

   */

  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);

      }

    });

  }

 

}

上述是最基础的一个ViewPager 下面我们就在这个基础上改造就可以了

实现无限循环滑动:

这里我事先循环滑动的方式很简单 就是把 adapter的count 设置为一个很大的值 这样 让它滑不到头 然后切换图片 就可以实现 虽然方法比较LOW 但是效果还是可以的 

代码在基础的ViewPager下修改如下 :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

public class MainActivity extends AppCompatActivity {

 

  private ViewPager topVp;

  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模拟存放要展示的图片

  private List<ImageView> imageViews ;

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    initImageViews();

    initVp();

  }

 

  /**

   * 初始化图片资源

   */

  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(); 修改如下

        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())); 删除此句 此句不删除 会出现 滑动中 布局消失的情况 因为被移除了 此处这样修改会影响一些性能。。。。。

      }

 

      @Override

      public Object instantiateItem(ViewGroup container, int position) {

//        container.addView(imageViews.get(position));

//        return imageViews.get(position); 修改如下

        try {

          container.addView(imageViews.get(position%imageViews.size()));

        }catch (Exception e){

 

        }

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

      }

    });

  }

 

}

这样 之后就可以实现无限循环右滑了 但是在程序刚启动 是 无法向左滑动的 要解决 很简单 只需要在开始的时候

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

即可 这样 就可以 实现 无限左右滑了

自动定时循环滑动:

下面增加自动定时左右滑动的功能 

要实现自动滑动 最主要的是 实现定时器功能我这里使用 Handler+Runnable的方法在上述代码的基础上 修改 如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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; //此处在Activity退出时及时 回收

 }

这之后 就可以实现自动滑动了

添加左下角圆形小按钮:

接下来添加 左下角的导航小原点 

首先 修改布局 :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

<?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>

我们需要的原点 要放在 LinearLayout布局中 

主要原理 就是向这个LinearLayout中动态添加 小圆点 即可

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

public class MainActivity extends AppCompatActivity {

 

  private ViewPager topVp;

  private int[]images = new int[]{R.mipmap.ad0, R.mipmap.ad1, R.mipmap.ad3}; //模拟存放要展示的图片

  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();

    /*

     * 计时器

     */

    handler = new Handler();

    handler.postDelayed(new TimerRunnable(),5000);

  }

 

  /**

   * 初始化小圆点

   */

  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;

  }

 

  /**

   * 初始化图片资源

   */

  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(); 修改如下

        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())); 删除此句

      }

 

      @Override

      public Object instantiateItem(ViewGroup container, int position) {

//        container.addView(imageViews.get(position));

//        return imageViews.get(position); 修改如下

        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);

        }

      }

    }

  }

}

给ViewPager添加切换动画:

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

调用 此行代码 可以添加 后面的TransFormer类 是自定义的过渡效果类

控制ViewPager 自动切换的速度

ViewPager自身的切换速度是写死的,我们无法修改,但是我们可以通过源码看到,ViewPager的切换速度是通过 Scroller类 控制的,而Scroller类中是可以设置过渡的时间的,因此 我们可以通过自己创建一个Scroller类 继承 Scroller 然后 通过反射 把ViewPager中的mScroller属性 设置成我们自己的可以设置时间的Scroller类即可 

下面是代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

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;

  }

}

反射修改ViewPager属性:

1

2

3

4

5

6

7

8

9

10

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错误啦");

    }

这样就可以控制速度了

好了,Android ViewPager广告页可无限循环滑动并可自动滚动带有小圆点的功能基本就实现了,具体参数大家可以自行设定

本文地址:https://blog.csdn.net/gxflh/article/details/107516530