Android ViewPager无限循环滑动并可自动滚动完整实例
作者:wdc 发布时间:2022-09-09 18:26:55
对于ViewPager 广告页这个功能很多APP都有这个功能在网上也看过一些资料,我就在这把我自己完整的实现方法写出来吧
基础的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>
很简单 仅仅是一个ViewPager
接下来简单的设置一下ViewPager的Adapter 添加ImageView
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下修改如下 :
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的方法在上述代码的基础上 修改 如下:
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退出时及时 回收
}
这之后 就可以实现自动滑动了
添加左下角圆形小按钮:
接下来添加 左下角的导航小原点
首先 修改布局 :
<?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中动态添加 小圆点 即可
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类即可
下面是代码:
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属性:
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广告页可无限循环滑动并可自动滚动带有小圆点的功能基本就实现了,具体参数大家可以自行设定
猜你喜欢
- 在Java SE中,对IO流与集合的操作在应用中比较重要。接下来,我以一个小型项目的形式,演示IO流、集合等知识点在实践中的运用。该项目名称
- 什么是死锁我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由
- 第一步:获取存储的路径 我们用/sdcard/Android/data/包名/的路径 方便我们测试查看 String path=MyAppl
- 将C语言封装成函数dll供C#端调用,需要传递的byte数组作为函数参数来传递。1、打开Visual Studio2017创建一个C的dll
- 本文实例讲述了C#采用递归实现阶乘的方法,供大家参考之用。通常来说,如果想实现一个阶乘,比如6 * 5 * 4 * 3 * 2 * 1,首先
- 1、Java版package com.lyz.utils.common; import java.io.UnsupportedEncodin
- 利用属性动画实现优酷菜单,供大家参考,具体内容如下布局文件<RelativeLayout xmlns:android="ht
- 前言众所周知Spring Boot是非常高效的开发框架,lombok是一套代码模板解决方案,将极大提升开发的效率,这里介绍给大家使用。文中详
- 1、正常dubbo调用流程引入dubbo依赖引入他人提供的clinet依赖包;配置相同的注册中心,使用@Reference注解注入对应的se
- 我们都知道可以用爬虫来找寻一些想要的数据,除了可以使用python进行操作,我们最近学习的java同样也支持爬虫的运行,本篇小编就教大家用j
- 最近在做一个搜索相关的项目,需要爬取网络上的一些链接存储到索引库中,虽然有很多开源的强大的爬虫框架,但本着学习的态度,自己写了一个简单的网络
- 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督。本文从最简单的一个排序算法——桶排序开始,分析桶排序的实现思路,代码实现,性
- 工程加入依赖:<dependency><groupId>org.apache.pdfbox</groupId&
- 本文实例讲述了android动态布局之动态加入TextView和ListView的方法。分享给大家供大家参考。具体实现方法如下:packag
- MyBatis 配置之集合的嵌套前言介绍在一些查询结果包装类中,包含一些 List 集合属性,使用 collection 标签可以声明该 L
- 本章,会对synchronized关键字进行介绍。涉及到的内容包括:1. synchronized原理2. synchronized基本规则
- 一、setting.xml文件的位置今天我们来谈谈Maven setting文件配置的禅定之道。不知道大家有没有听说过禅宗?嗯,没错,就是那
- 题外话:学习.NET已经有一年了,从C#->ASP.NET->WPF。主要以看电子书为主,比较少写代码。现在回头学习以前接触过的
- 实践仿照@EnableEurekaServer实现自动装配如果你使用过Eureka作为微服务的注册中心,那么对@EnableWebConfi
- 1.关于JSR-303JSR-303规范(Bean Validation规范)提供了对 Java EE 和 Java SE 中的 Java