ViewPager可以实现多页面滑动切换以及动画效果,在很多开发场合都十分常用,不仅方便实用而且功能强大。ViewPager类直接继承了ViewGroup类,所以它是一个容器类,可以在其中添加其他的view类。
ViewPager是Google SDK自带的附加包v4包的类(即android.support-v4.jar),所以在写布局文件时需要引用完整类名。经验表明这样一个View必然要用到适配器,Android为它定制了专属的适配器PagerAdapter。
ViewPager主要特点是可通过触屏滑动来切换界面,也可以通过标签点击切换界面,在滑动的过程中指示位置的头标或下标也会跟着滑动,而不是直接闪过去。当然,这么细致全面的功能需要复杂完善的代码作为后台,每一个细节都有一个逻辑。ViewAdapter虽然看起来复杂,但套路都是固定的。以下做两个简单的实现,是两种比较常见的模式,一个是App更新后的新手指引界面,一个是App中通过点击和滑动切换的界面。
可以通过setCurrentItem()方法设置显示第几个界面(从0开始)。

其实做这样的东西难点并不在于如何填充数据,而是在于作为标签的小灰点或者小蓝条的动画过程,ViewPager提供了界面切换的动画,但是标签的动画仍需要程序员写代码实现。

第一个实例,布局如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.briup.viewpager.MainActivity" ><!-- Viewpager:全类名导入 --><android.support.v4.view.ViewPagerandroid:id="@+id/viewpager"android:layout_width="match_parent"android:layout_height="match_parent" /><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="50dp" ><!-- 灰点所在的布局,假设所要显示的界面数量不确定,所以灰点需要在Java代码中绘制 --><LinearLayoutandroid:id="@+id/ll_item"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal" ></LinearLayout><!-- 蓝点:由shape绘制的图片,将灰点的布局和蓝点放在同一个相对布局中,这样后面加入的蓝点就回覆盖灰点,达到想要的效果 --><ImageViewandroid:id="@+id/blue_iv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/blue_point" /></RelativeLayout><!-- 开始体验按钮,首先它并不是在每个界面都显示的所以它的默认值应设为不可见 --><Buttonandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="100dp"android:background="@drawable/btn_shape"android:text="开始体验"android:textColor="#00ffff"android:visibility="gone" /></RelativeLayout>

蓝点shape文件blue_point.xml如下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"><size android:width="7dp"android:height="7dp"/><solid android:color="#18a1ff"/>
</shape>

灰点shape文件grey_point.xml如下,两个其实一样,只是填充颜色不同

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"><size android:width="7dp"android:height="7dp"/><solid android:color="#c3c3c3"/>
</shape>

开始体验按钮shape文件btn_shape.xml如下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><corners android:radius="20dp"/><solid android:color="#ffffff"/><stroke android:width="2dp"android:color="#00ffff"/><padding android:left="10dp"android:top="5dp"android:right="10dp"android:bottom="5dp"/>
</shape>

MainActivity.class类文件如下

import java.util.ArrayList;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.Toast;public class MainActivity extends Activity {private ViewPager viewPager;private LinearLayout ll_item;//灰点所在的线性布局private ImageView blue_iv;//小蓝点private Button btn;int position;//当前界面数(从0开始)private int pointWidth;//小灰点的距离private int[] images = {R.drawable.p1,R.drawable.p2,R.drawable.p3};//新手导航一般都是图片做界面private List<ImageView> list;//存放图片控件的List集合@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);//设置App不显示菜单,黑乎乎的不好看//注意这两句代码的顺序,上面一句写在下面一句后面会报错setContentView(R.layout.activity_main);viewPager = (ViewPager) findViewById(R.id.viewpager);list = new ArrayList<ImageView>();ll_item = (LinearLayout) findViewById(R.id.ll_item);blue_iv = (ImageView) findViewById(R.id.blue_iv);btn = (Button) findViewById(R.id.btn);//开始按钮做一个简单的测试,前面两个界面开始按钮是不可见的,同时也是点不到的btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "Click", Toast.LENGTH_SHORT).show();}});//将图片的引用转化为图片控件存在List的集合中for(int i=0;i<images.length;i++){ImageView imageView = new ImageView(this);imageView.setImageResource(images[i]);//将相应的图片设置到IamageViewimageView.setScaleType(ScaleType.FIT_XY);//设置图片的拉伸方式为充满list.add(imageView);//绘制小灰点儿,有几个界面就绘制几个ImageView points = new ImageView(this);points.setImageResource(R.drawable.grey_point);//通过shape文件绘制好灰点//给第一个以外的小灰点儿设置左边距,保证三个灰点水平居中LinearLayout.LayoutParams lllp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);//拿到灰点所处的线性布局一样的形状(一些距离属性)if(i>0)lllp.leftMargin = 30;//设置左外边距,像素points.setLayoutParams(lllp);//把设置好左外边距的形状设置给灰点ll_item.addView(points);//将灰点加入线性布局}//为了完成蓝点在界面滑动时的动画效果,必须获取到灰点的边距,通过动态的给蓝点设置边距来完成动画效果//由于在执行onCreate方法时,界面还没有绘制完成,无法获取pointWidth,设定小蓝点绘制完成的事件监听,当小蓝点绘制完成再获取blue_iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//获取小灰点圆心间的距离,第1个灰点和第二个灰点的距离pointWidth = ll_item.getChildAt(1).getLeft()-ll_item.getChildAt(0).getLeft();}});VPAdapter vpAdapter = new VPAdapter();//创建适配器viewPager.setAdapter(vpAdapter);//ViewPager加载适配器//为ViewPager设定监听器,界面是滑动时让蓝点也跟着动viewPager.addOnPageChangeListener(new OnPageChangeListener() {@Override//当前选中第几个界面public void onPageSelected(int arg0) {position = arg0;}/*** 界面滑动时回调此方法* arg0:当前界面数* arg1:界面滑动过的百分数(0.0-1.0)* arg2:当前界面偏移的像素位置*/@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {int width;//小蓝点当前滑动距离width = (int) (arg1*pointWidth+arg0*pointWidth);//1个界面就要一个小灰点的距离,再加上滑动过的百分比距离就是当前蓝点的位置RelativeLayout.LayoutParams rllp= (LayoutParams) blue_iv.getLayoutParams();//拿到蓝点所在布局的形状rllp.leftMargin=width;//设置蓝点的左外边距blue_iv.setLayoutParams(rllp);//将设置好的形状设置给蓝点//开始体验按钮只能出现在最后一页,并且在滑动的过程中保持消失,这样效果更好,不信可以把后面的判断删去,在最后一页回移的时候,按钮先会跟着移动,然后突然就不见了if(position==images.length-1&&arg1==0)btn.setVisibility(View.VISIBLE);elsebtn.setVisibility(View.INVISIBLE);}//状态改变时调用:arg0=0还没滑动,arg0=1正在滑动,arg0=2滑动完毕@Overridepublic void onPageScrollStateChanged(int arg0) {}});}class VPAdapter extends PagerAdapter{//返回ViewPager中总页数@Overridepublic int getCount() {return images.length;}//判断视图是否由对象生成@Overridepublic boolean isViewFromObject(View view, Object object) {return view==object;}@Override/*** 返回将哪一个对象放在当前ViewPager中* container:每一页的父容器* position:当前页(从0开始)*/public Object instantiateItem(ViewGroup container, int position) {//浪费资源,每次滑到新的页都会创建新的的ImageView,我们选择先把ImageView控件存在List集合中,再按需要获取
//          ImageView imageView = new ImageView(MainActivity.this);
//          imageView.setImageResource(images[position]);ImageView imageView = list.get(position);container.addView(imageView);return imageView;}@Override/*** 从ViewPager中移除View对象*/public void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}}

效果如下

滑动时,蓝点也跟随移动

按钮点击测试

第二个实例,布局文件如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff" ><RelativeLayoutandroid:id="@+id/rl_title_top"android:layout_width="match_parent"android:layout_height="wrap_content" ><!-- 标签卡:也可以使用TextView,由于没有制作shape,这里又用了白色背景,按钮点击没有效果,但是蓝条可以告诉你点击成功了 --><LinearLayoutandroid:id="@+id/ll_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><Buttonandroid:id="@+id/btn1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:background="#ffffff"android:text="吸血鬼"android:textSize="20sp" /><Buttonandroid:id="@+id/btn2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:background="#ffffff"android:text="木乃伊"android:textSize="20sp" /><Buttonandroid:id="@+id/btn3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:background="#ffffff"android:text="雪怪"android:textSize="20sp" /></LinearLayout><RelativeLayoutandroid:id="@+id/rl_progress"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/ll_title" ><!-- 标签和可切换界面的分界,标志位置的蓝条通过Java代码加入,相对布局,直接加入就回覆盖分界 --><Viewandroid:layout_width="match_parent"android:layout_height="10dp"android:background="#eeeeee" /></RelativeLayout></RelativeLayout><!-- Viewpager:全类名导入 --><android.support.v4.view.ViewPagerandroid:id="@+id/viewpager"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentBottom="true"android:layout_below="@id/rl_title_top" /></RelativeLayout>

蓝条shape文件progress.xml如下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#0000ff"/><corners android:radius="10dp"/>
</shape>

MainActivity.class类文件如下

import java.util.ArrayList;
import java.util.List;import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;public class MainActivity extends Activity {private ViewPager vp;private Button btn1,btn2,btn3;private RelativeLayout rl_progress;//分隔标签和界面的分界布局,把蓝条加入这个布局就能达到想要的效果private VPAdapter vpa;private int[] items = {R.drawable.a49,R.drawable.a53,R.drawable.a57};//这里用简单的图片代替界面private List<ImageView> list;private TextView view;//因为蓝条的宽度需要通过代码获取屏幕宽度来计算,所以蓝条在Java代码中绘制//蓝条使用一个TextView绘制,其他View也可以private int width;//蓝条的宽度,或者说屏幕宽度n等分的长度@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);vp = (ViewPager) findViewById(R.id.viewpager);btn1 = (Button) findViewById(R.id.btn1);btn2 = (Button) findViewById(R.id.btn2);btn3 = (Button) findViewById(R.id.btn3);rl_progress = (RelativeLayout) findViewById(R.id.rl_progress);list = new ArrayList<ImageView>();view = new TextView(this);//获取屏幕宽度的方法DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);width = metrics.widthPixels/items.length;//由于我这里只有3个界面,所以我只要设置蓝条宽度为屏幕宽/3(metrics.widthPixels/3)view.setWidth(width);view.setHeight(25);//多次尝试才设置成正好的高度,shape文件中设置和布局文件相同的高度(10dp)却要大一些view.setBackground(getResources().getDrawable(R.drawable.progress));//shape文件中设置了蓝条为蓝色背景、圆角rl_progress.addView(view);//把蓝条加入到相对布局for(int i=0;i<items.length;i++){ImageView iv = new ImageView(this);iv.setImageResource(items[i]);iv.setScaleType(ScaleType.FIT_XY);list.add(iv);}vpa = new VPAdapter();vp.setAdapter(vpa);vp.addOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {int left = width*arg0 + (int) (width*arg1);//蓝条滑动的距离RelativeLayout.LayoutParams rllp = (LayoutParams) view.getLayoutParams();rllp.leftMargin = left;view.setLayoutParams(rllp);}@Overridepublic void onPageScrollStateChanged(int arg0) {}});//标签按钮的监听事件:点到哪个就切换到那一个界面btn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {vp.setCurrentItem(0);}});btn2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {vp.setCurrentItem(1);}});btn3.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {vp.setCurrentItem(2);}});}class VPAdapter extends PagerAdapter{@Overridepublic int getCount() {return items.length;}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0==arg1;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {ImageView iv = list.get(position);container.addView(iv);return iv;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}
}

效果如下

滑动时,蓝条跟着移动

Android中实现页面滑动——ViewPager相关推荐

  1. android中view手势滑动冲突的两种解决方法

    android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...

  2. Android中实现照片滑动时左右进出的动画的xml代码

    场景 Android中通过ImageSwitcher实现相册滑动查看照片功能(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/det ...

  3. android中设置页面边距,如何在android中使用代码在imageview上设置边距?

    我想在运行时创建一个布局,然后我想在运行时使用循环添加一些imageview.但问题是我使用LayoutParams的余量根本无法工作.我尝试了很多,但没有找到任何解决方案.我也附加我的代码.如何在a ...

  4. android中可左右滑动输入框

    在网上无意看到一个UI动画,用户输入身份证信息时可以左右滑动输入框进行输入,并且信息可以实时显示.闲下之余,自己就动手用代码实现出来了,废话不多说,开始讲讲如何实现制作的. 1,布局制作 先写一个主界 ...

  5. Android中使用PhotoView和ViewPager查看图片,并保存到本地

    如下图:可以滑动查看,可以放大缩小,点击长按保存图片     build.gradle中添加依赖 compile 'com.github.chrisbanes.photoview:library:+' ...

  6. android studio多页面滑动,Android Studio之多个Activity的滑动切换(二)

    1.由于Android界面上的所有控件一般都位于Layout控件(比如RelativeLayout)之上,而布局控件可以设置响应touch事件,所以可以通过布局控件的setOnTouchListen来 ...

  7. Android中禁止WebView滑动

    参考网址:https://blog.csdn.net/Agg_bin/article/details/82226304 https://www.cnblogs.com/renhui/articles/ ...

  8. android中h5页面播放声音,【报Bug】h5+的Android版的打包之后无法播放声音

    详细问题描述 (DCloud产品不会有明显的bug,所以你遇到的问题大都是在特定环境下才能重现的问题,请仔细描述你的环境和重现方式,否则DCloud很难排查解决你的问题) [内容] 重现步骤 [步骤] ...

  9. Android中的自定义View(一)

    文章收藏的好句子:成功从来不是一蹴而就,而是日积月累的努力叠加的结果. ps:本文是基于 Android API 31 来分析的,文章写的 demo 是用 AndroidStudio 工具来开发的. ...

最新文章

  1. 暴雪游戏遭遇AI“实力”坑队友:四处游走,还不参与战斗
  2. CCF推荐系统项目代码解读!
  3. 你没见过Java台式计算机和Java操作系统吧
  4. Struts2 之 ActionContext获取WEB资源
  5. 光储充一体化充电站_广东东莞首座光储充一体化智能充电站 “变废为宝”收益可观...
  6. C/C++常见标准头文件前格式探讨
  7. datax参数设置_DataX-操作HDFS
  8. ecshop 实现购物车退出不清空
  9. Win10 虚拟机安装 Windows xp(professional sp3)简记(非教学)
  10. 2021-10-24 J1939故障代码
  11. debugger vsm_proteus vsm 仿真
  12. 扩展欧几里得求乘法逆元 - 手算(结尾附视频)
  13. 洛谷 P1724 东风谷早苗
  14. oracle数据库重启命令是什么
  15. 反射机制之取得类的结构
  16. 用c语言写图书馆程序,用c语言写图书馆管理系统
  17. java_vinson_03:java变量与常量
  18. Centos系统下搭建Smokeping 方法
  19. Android自定义适配器
  20. 【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗

热门文章

  1. 计算机主机声音怎么办,电脑主机噪音怎么办?
  2. 闪耀暖暖总是显示服务器连接失败,《闪耀暖暖》服务器连接失败怎么办 当前无网络链接怎么办...
  3. 【深度学习】新垣结衣夫妇的孩子长啥样,用 BabyGAN 预测试试
  4. 2023年全国最新安全员精选真题及答案63
  5. Libmad音频解码库的编译和使用
  6. 03 Redis 网络IO模型简介
  7. 【北邮国院大三下】Logistics and Supply Chain Management 物流与供应链管理 Week1
  8. OSChina 周五乱弹 —— 听说富婆需要我这个快乐球
  9. 计算机毕业论文选题推荐|软件工程|信息管理|数据分析|系列一
  10. 资深架构师谈 DDD 兴起,解决难题与实现步骤