ViewPage最全解析
简单说明:
ViewPager是android扩展包v4包中的类,直接继承了ViewGroup类,和LinearLayout等布局一样,都是一个容器,需要在里面添加我们想要显示的内容。
一、在xml中添加ViewPager
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@id/bannerContainer"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false"><android.support.v4.view.ViewPagerandroid:id="@id/bannerViewPager"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false" />
注:除了通过xml代码来定义一个ViewPager外,同其他控件一样也可以动态添加。
二、定义ViewPageAdapter
1、可以在构造函数中传递ViewPager需要加载显示的数据。
2、必须重载的函数:
a) Determines whether a page View is associated with a specific key object return by instantiateItem(ViewGroup ,int)
public abstract boolean isViewFromObject(View view, Object object);
b) 获取Pager的总页数
/*** Return the number of views available.*/public abstract int getCount();
c)干函数中需要将 页面需要加载的内容添加到container中,同时将需要加载的view返回。该函数是PagerAdapter的核心,具体可以参照下面代码
/*** Create the page for the given position. The adapter is responsible* for adding the view to the container given here, although it only* must ensure this is done by the time it returns from* {@link #finishUpdate(ViewGroup)}.** @param container The containing View in which the page will be shown.* @param position The page position to be instantiated.* @return Returns an Object representing the new page. This does not* need to be a View, but can be some other container of the page.*/public Object instantiateItem(ViewGroup container, int position) {return instantiateItem((View) container, position);}
d)该函数负责对ViewGroup中已经添加的部分资源进行回收
(遇到过当没有重载该函数时,滑动到图片页数第三张时,activity自动结束返回到上一个Activity。具体原因有待分析)
/*** Remove a page for the given position. The adapter is responsible* for removing the view from its container, although it only must ensure* this is done by the time it returns from {@link #finishUpdate(ViewGroup)}.** @param container The containing View from which the page will be removed.* @param position The page position to be removed.* @param object The same object that was returned by* {@link #instantiateItem(View, int)}.*/public void destroyItem(ViewGroup container, int position, Object object) {destroyItem((View) container, position, object);}
e) destoryItem() 和 instantiateItem() 执行顺序问题:下图为 移动一个viewpage时 这两个函数打印的 position
ViewPager启动时,第一个和第二个页面已经加载完成。
当再次滑动时,先加载第三个页面,然后再销毁第一个页面。(如果这时返回第1个页面,则先加载第一个页面再销毁第三个页面)
总之,除了第一个后最后一个页面外,ViewPager总会保持左右两侧的页面已经加载完成。
3、 PagerAdapter 还有 FragementPagerAdapter 用于加载Fragment。 (用普通的PagerAdapter加载Fragment的区别)
FragementStatePagerAdapter : 当页数较多时还可以使用该Adapter。
PagerAdapter的实现代码:
/*** PagerAdapter的实现* */public class DripPageGuideAdapter extends PagerAdapter {@Overridepublic Object instantiateItem(ViewGroup container, int position) {container.addView(mViews.get(position));return mViews.get(position);}@Overridepublic int getCount() {return totalSize;}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View)object);}}
View Code
三、 activity中定义viewpage,始化相关控件,并绑定二中定义的adapter
1、加载ViewPager,绑定Adapter
public class ViewPageActivity extends Activity {private ViewPager viewPager;private ViewPageAdapter adapter;private Set<String> citiesSHaredPreference;private Context context = ViewPageActivity.this;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_viewpage);citiesSHaredPreference = new HashSet<String>();citiesSHaredPreference.add("huoshan");citiesSHaredPreference.add("hefei");citiesSHaredPreference.add("shanghai");initLoadData();initView();}private void initLoadData(){for(int i=0;i<citiesSHaredPreference.size();i++){}}private void initView() {viewPager = (ViewPager) findViewById(R.id.viewpage);adapter = new ViewPageAdapter(context,citiesSHaredPreference);viewPager.setAdapter(adapter);} }
当在adapter中添加图片时,如果要想图片适应ViewPager大小,需要设置: imageView.setScaleType(ImageView.ScaleType.FIT_XY);
2、可以在布局中添加页面指示器: 圆圈/数字/横线,并且当滑动到某一页面时,指示器颜色出现变化。
void createIndicator() {List<ImageView> indicatorImages = new ArrayList<>();for (int i = 0; i < 2; i++) {ImageView imageView = new ImageView(mContext);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(90, 90);params.leftMargin = 5; params.rightMargin = 5; if (i == 0) { //imageView.setImageResource(R.drawable.gray_radius); imageView.setImageDrawable(IndicatorShapes.getGrayShape()); } else { imageView.setImageDrawable(IndicatorShapes.getWhiteShape()); } indicatorImages.add(imageView); mIndicator.addView(imageView, params); } }
仅仅初始化指示器还不够,还需要在滑动页面的时候指示器的颜色也跟随着改变,要达到此效果需设置viewpager的监听器:
定一个lastPosition变量,初始值为0,当页面滑动时,需要把上一页面的指示器颜色恢复,同时设置当前页面为选中状态。
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {if(GuideConfig.isShowIndicator){indicatorImages.get((lastPosition + totalSize) % totalSize).setImageDrawable(IndicatorShapes.getUnselectedShape());indicatorImages.get((position + totalSize) % totalSize).setImageDrawable(IndicatorShapes.getSelectedShape());}lastPosition = position;mListener.onPageSelected(totalSize,position);}@Overridepublic void onPageScrollStateChanged(int state) {}}});
指示器开源库推荐:
a、 安卓大神的 : https://github.com/JakeWharton/ViewPagerIndicator
该库长时间没有维护,因为是大神的所以放在第一个
b、一个比我还年轻的人写的,自惭形秽:https://github.com/hackware1993/MagicIndicator
3、滑动到最后页面再滑动监听事件: 很多业务需要当再滑动最后一个页面时需要跳转到下一个Activity的需求
那么如何实现呢,其实就是在上面的监听接口中就能实现,可参考:http://blog.csdn.net/nn955/article/details/46240371
4、滑动到最后页面继续向左拖动时,会有 半透明的条出现,如何禁止该条的出现
四、ViewPager setOnPageChangeListener方法
OnPageChangeListener接口中定义了三个函数:
1.onPageSelected(int position):这个方法有一个参数position,代表哪个页面被选中。当用手指滑动翻页的时候,如果翻动成功了(滑动的距离够长),手指抬起来就会立即执行这个方法,position就是当前滑动到的页面。如果直接setCurrentItem翻页,那position就和setCurrentItem的参数一致,这种情况在onPageScrolled执行方法前就会立即执行。
2.onPageScrolled(int position,float positionOffset, int positionOffsetPixels):这个方法会在屏幕滚动过程中不断被调用。
有三个参数,第一个position,这个参数要特别注意一下。当用手指滑动时,如果手指按在页面上不动,position和当前页面index是一致的;如果手指向左拖动(相应页面向右翻动),这时候position大部分时间和当前页面是一致的,只有翻页成功的情况下最后一次调用才会变为目标页面;如果手指向右拖动(相应页面向左翻动),这时候position大部分时间和目标页面是一致的,只有翻页不成功的情况下最后一次调用才会变为原页面。
当直接设置setCurrentItem翻页时,如果是相邻的情况(比如现在是第二个页面,跳到第一或者第三个页面),如果页面向右翻动,大部分时间是和当前页面是一致的,只有最后才变成目标页面;如果向左翻动,position和目标页面是一致的。这和用手指拖动页面翻动是基本一致的。
如果不是相邻的情况,比如我从第一个页面跳到第三个页面,position先是0,然后逐步变成1,然后逐步变成2;我从第三个页面跳到第一个页面,position先是1,然后逐步变成0,并没有出现为2的情况。
positionOffset是当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变为0。如果页面向左翻动,这个值不断变小,最后变为0。
positionOffsetPixels是当前页面滑动像素,变化情况和positionOffset一致。
3.onPageScrollStateChanged(int state):这个方法在手指操作屏幕的时候发生变化。有三个值:0(END),1(PRESS) , 2(UP) 。
当用手指滑动翻页时,手指按下去的时候会触发这个方法,state值为1,手指抬起时,如果发生了滑动(即使很小),这个值会变为2,然后最后变为0 。总共执行这个方法三次。一种特殊情况是手指按下去以后一点滑动也没有发生,这个时候只会调用这个方法两次,state值分别是1,0 。
当setCurrentItem翻页时,会执行这个方法两次,state值分别为2 , 0 。
三个方法的执行顺序为:用手指拖动翻页时,最先执行一遍onPageScrollStateChanged(1),然后不断执行onPageScrolled,放手指的时候,直接立即执行一次onPageScrollStateChanged(2),然后立即执行一次onPageSelected,然后再不断执行onPageScrollStateChanged,最后执行一次onPageScrollStateChanged(0)。
易忽视问题:
OnPageSelected 方法会有一个问题,当ViewPager第一个页面显示(position 为0)的时候该方法不会被调用。解决办法:
将OnPageSelected 定义成一个私有成员变量,在调用mViewPager.setOnPageChangeListener(mOnPagerChageListener)之后马上调用
mOnPageChangeListener.OnPageSelected(0);
五、如何给页面滑动添加自定义的动画
六、OOM问题
当ViewPager滑动图片较多或者图片较大时容易出现OOM,那么如何优化图片加载呢:
七、关于ViewPager相关的开源库推荐
1、广告轮播,可循环自动播放: https://github.com/youth5201314/banner
2、基于ViewPage的引导页面例子: https://github.com/matrixxun/ProductTour
上面两个只是很实用的库,github上很多炫酷的viewPager效果,有时间可以研究下。
转载于:https://www.cnblogs.com/NeilZhang/p/6891231.html
ViewPage最全解析相关推荐
- Go modules基础精进,六大核心概念全解析(下)
Go 语言做开发时,路径是如何定义的?Go Mudules又为此带来了哪些改变?本文将会全面介绍Go Modules六大核心概念,包括了设计理念与兼容性原则等,掌握这些技术点对于管理和维护Go 模块有 ...
- 第四章:Spring项目文件上传两种方式(全解析)
欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...
- 阿里秋招面试全解析(含内推岗)
每个技术人都有个大厂梦,我觉得这很正常,并不是饭后的谈资而是每个技术人的追求.像阿里.腾讯.美团.字节跳动.京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司/小公司,如果说能够在这样的公司锻 ...
- Apache Web服务器访问控制机制全解析
Apache Web服务器访问控制机制全解析 原文请见: http://netsecurity.51cto.com/art/201102/245666.htm Linux下的Aapche服务器提供了强 ...
- 6.15 Unity引擎渲染效率全解析
UWA新晋主播赵福恺从Unity渲染模块中的各种渲染效果性能.PBR渲染性能以及阴影的渲染性能三个角度分别进行了详细的分析总结.为响应各大听众的需求,小编奉上完整视频回顾,同时也向看完直播才下班的五好 ...
- python读取txt文件写入-Python读写txt文本文件的操作方法全解析
一.文件的打开和创建 >>> f = open('/tmp/test.txt') >>> f.read() 'hello python! hello world! ...
- jQuery Ajax 实例 全解析(转)
jQuery Ajax 实例 全解析 jQuery确实是一个挺好的轻量级的JS框架,能帮助我们快速的开发JS应用,并在一定程度上改变了我们写JavaScript代码的习惯. 废话少说,直接进入正题,我 ...
- Fragment全解析系列
文/YoKey(简书作者) 原文链接:http://www.jianshu.com/p/d9143a92ad94 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". F ...
- 万物之始正则表达式全解析三部曲(中篇)-正则表达式运算符优先级及匹配规则
前言 各位小伙伴大家好,接下来几天时间,我会从多个角度对正则表达式进行系统阐述,让你了解正则表达式的前世今生. 该系列文章上篇 万物之始正则表达式全解析三部曲(上篇)-正则表达式基础知识及语法 以下是 ...
最新文章
- 6个步骤,告诉你如何用树莓派和机器学习DIY一个车牌识别器!(附详细分析)...
- 联合国召开会议讨论“杀手机器人”问题
- Vue 学习笔记 (一) -- 初识 VueCli 3
- Linux脚本自动安装软件,一个快速自动安装Apache及其相关软件的Shell脚本
- oracle 错误: ORA-12899:始终提示字段太大
- 如何应对多GPU大规模训练的挑战?
- python读取字典元素笔记_python学习笔记:字典的使用示例详解
- 回忆自己的大学四年得与失
- Java命令行界面(第7部分):JCommander
- 计算机信息管理专业教学改革,计算机信息管理专业实践教学改革探索
- brocadcastReceiver
- C++基础语法-01-引用
- Python解释器(Interpreter)介绍
- 第3章 形式语言与自动机
- 谷歌学术高级搜索技巧
- 解析java数值类型数据混合运算
- Excel文件处理-Python之openpyxl
- idea 新手创建Spring项目
- [2021.8纪中集训Day14]
- 引用feignClient对象项目启动异常-Consider defining a bean of type ‘com.xxx.service.xxxRemote‘ in your configura
热门文章
- poj3252Round Numbers
- c语言中的switch语句中的break和continue的作用
- jbpm 5 安装教程
- SQL中的数据转换服务,数据库迁移
- 最近自学 Asp.net MVC 小总结
- Flutter中Contrainer 组件的宽高限制分析
- JavaScript 中 Number
- 使用 Pandas 的 to_excel() 方法来将多个 csv 文件合并到一个 xlsx 的不同 sheets 内
- Codeforces 977D: Divide by three, multiply by two(暴力)
- Oracle创建表语句(Create table)语法详解及示例