Android中实现页面滑动——ViewPager
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相关推荐
- android中view手势滑动冲突的两种解决方法
android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...
- Android中实现照片滑动时左右进出的动画的xml代码
场景 Android中通过ImageSwitcher实现相册滑动查看照片功能(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/det ...
- android中设置页面边距,如何在android中使用代码在imageview上设置边距?
我想在运行时创建一个布局,然后我想在运行时使用循环添加一些imageview.但问题是我使用LayoutParams的余量根本无法工作.我尝试了很多,但没有找到任何解决方案.我也附加我的代码.如何在a ...
- android中可左右滑动输入框
在网上无意看到一个UI动画,用户输入身份证信息时可以左右滑动输入框进行输入,并且信息可以实时显示.闲下之余,自己就动手用代码实现出来了,废话不多说,开始讲讲如何实现制作的. 1,布局制作 先写一个主界 ...
- Android中使用PhotoView和ViewPager查看图片,并保存到本地
如下图:可以滑动查看,可以放大缩小,点击长按保存图片 build.gradle中添加依赖 compile 'com.github.chrisbanes.photoview:library:+' ...
- android studio多页面滑动,Android Studio之多个Activity的滑动切换(二)
1.由于Android界面上的所有控件一般都位于Layout控件(比如RelativeLayout)之上,而布局控件可以设置响应touch事件,所以可以通过布局控件的setOnTouchListen来 ...
- Android中禁止WebView滑动
参考网址:https://blog.csdn.net/Agg_bin/article/details/82226304 https://www.cnblogs.com/renhui/articles/ ...
- android中h5页面播放声音,【报Bug】h5+的Android版的打包之后无法播放声音
详细问题描述 (DCloud产品不会有明显的bug,所以你遇到的问题大都是在特定环境下才能重现的问题,请仔细描述你的环境和重现方式,否则DCloud很难排查解决你的问题) [内容] 重现步骤 [步骤] ...
- Android中的自定义View(一)
文章收藏的好句子:成功从来不是一蹴而就,而是日积月累的努力叠加的结果. ps:本文是基于 Android API 31 来分析的,文章写的 demo 是用 AndroidStudio 工具来开发的. ...
最新文章
- 暴雪游戏遭遇AI“实力”坑队友:四处游走,还不参与战斗
- CCF推荐系统项目代码解读!
- 你没见过Java台式计算机和Java操作系统吧
- Struts2 之 ActionContext获取WEB资源
- 光储充一体化充电站_广东东莞首座光储充一体化智能充电站 “变废为宝”收益可观...
- C/C++常见标准头文件前格式探讨
- datax参数设置_DataX-操作HDFS
- ecshop 实现购物车退出不清空
- Win10 虚拟机安装 Windows xp(professional sp3)简记(非教学)
- 2021-10-24 J1939故障代码
- debugger vsm_proteus vsm 仿真
- 扩展欧几里得求乘法逆元 - 手算(结尾附视频)
- 洛谷 P1724 东风谷早苗
- oracle数据库重启命令是什么
- 反射机制之取得类的结构
- 用c语言写图书馆程序,用c语言写图书馆管理系统
- java_vinson_03:java变量与常量
- Centos系统下搭建Smokeping 方法
- Android自定义适配器
- 【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗
热门文章
- 计算机主机声音怎么办,电脑主机噪音怎么办?
- 闪耀暖暖总是显示服务器连接失败,《闪耀暖暖》服务器连接失败怎么办 当前无网络链接怎么办...
- 【深度学习】新垣结衣夫妇的孩子长啥样,用 BabyGAN 预测试试
- 2023年全国最新安全员精选真题及答案63
- Libmad音频解码库的编译和使用
- 03 Redis 网络IO模型简介
- 【北邮国院大三下】Logistics and Supply Chain Management 物流与供应链管理 Week1
- OSChina 周五乱弹 —— 听说富婆需要我这个快乐球
- 计算机毕业论文选题推荐|软件工程|信息管理|数据分析|系列一
- 资深架构师谈 DDD 兴起,解决难题与实现步骤