ViewPaer的笔记
ViewPager在日常的APP中是一个不可或缺的控件,图片浏览,广告轮播都需要这个控件,所以掌握这个控件是必须的。
最简单的实践
实现Viewpager的三要素:时间、地点、人物。呸呸呸,说到语文去。应该是ViewPager控件,ViewPager的适配器,ViewPgaer需要显示的内容。接下来就是实现一下
内容代码(其余的内容就是变换一下背景颜色):
<?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:background="@color/colorAccent">
<TextView
android:textColor="#FFF"
android:layout_gravity="center"
android:textSize="50dp"
android:text="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
然后就是召唤5个View并塞进集合里面去
List<View> mList = new ArrayList<>();
View view1 = LayoutInflater.from(this).inflate(R.layout.view1, null, false);
View view2 = LayoutInflater.from(this).inflate(R.layout.view2, null, false);
View view3 = LayoutInflater.from(this).inflate(R.layout.view3, null, false);
View view4 = LayoutInflater.from(this).inflate(R.layout.view4, null, false);
View view5 = LayoutInflater.from(this).inflate(R.layout.view5, null, false);
mList.add(view1);
mList.add(view2);
mList.add(view3);
mList.add(view4);
mList.add(view5);
然后就是初始化Adapter并把数据放进去
private PagerAdapter adapter = new PagerAdapter() {
// getCount():返回要滑动的VIew的个数
@Override
public int getCount() {
return 1000;
}
// 该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key
// 与一个页面视图是否是代表的同一个视图(即它俩是否是对应的,
// 对应的表示同一个View)
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// instantiateItem():做了两件事,
// 第一:将当前视图添加到container中,
// 第二:返回当前View
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mList.get(position % mList.size()));
return mList.get(position % mList.size());
}
// destroyItem():从当前container中删除指定位置(position)的View;
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mList.get(position % mList.size()));
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
};
然后将设配器和控件联系起来联系起来 于是乎一个ViewPager控件的使用就大功告成。
效果如下:
然后就是解析一下每一个方法的作用
public int getCount()
就是返回有多小个Item
public Object instantiateItem(ViewGroup container, int position)
instantiateItem():做了两件事
第一:将当前视图添加到container中
第二:返回当前View
public void destroyItem(ViewGroup container, int position, Object object)
destroyItem():从当前container中删除指定位置(position)的View;
public boolean isViewFromObject(View view, Object object)
该函数用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图(即它俩是否是对应的表示同一个View)
public int getItemPosition(Object object) {
return POSITION_NONE;
}
删除的时候 重写adapter的getItemPosition方法,返回值设为POSITION_NONE,调用notifydatasetchanged通知viewpager更新才会生效
如果ViewPager的Item不复杂可以直接这么写,这样会重绘所有item
因为点击删除之后界面没有立即重绘所有做浏览图片删除图片的时候最好加上,但是做广告轮循最好还是不要加上。
关于设配器(PageAdapter:像我这么吊的还有两个)
适配器不知只有PageAdapter还有FragmentPagerAdapter
和FragmentStatePagerAdapter
后面两个的内容都是Fragment但是他们还是有区别的,不然要两个干什么。
这两个Adapter需要传入FragmentManger进行管理。
我写不出比原作者更好的文字,所以引用了。
FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。FragmentPagerAdapter 重载实现了几个必须的函数,因此来自 PagerAdapter 的函数,我们只需要实现 getCount(),即可。且,由于 FragmentPagerAdapter.instantiateItem() 的实现中,调用了一个新增的虚函数 getItem(),因此,我们还至少需要实现一个 getItem()。因此,总体上来说,相对于继承自 PagerAdapter,更方便一些。
FragmentStatePagerAdapter 和前面的 FragmentPagerAdapter 一样,是继承子 PagerAdapter。但是,和 FragmentPagerAdapter 不一样的是,正如其类名中的 ‘State’ 所表明的含义一样,该 PagerAdapter 的实现将只保留当前页面,当页面离开视线后,就会被消除,释放其资源;而在页面需要显示时,生成新的页面(就像 ListView 的实现一样)。这么实现的好处就是当拥有大量的页面时,不必在内存中占用大量的内存。
ViewPager的动画
相关的方法就主要是PageTransformer
主要就是继承这个达到动画的显现
@Override
public void transformPage(View page, float position) {}
我们继承这个方法有什么用。page是传进来的页面 即使当前手机可见得到页面。而position则代表页面的滑动问题,范围[-1,1]
接下来就容易了
滑到下一页是从0到1,滑动到上一页是 -1到0
这里的代码是引用的
position的可能性的值有,其实从官方示例的注释就能看出:
[-Infinity,-1)已经看不到了
(1,+Infinity]已经看不到了
[-1, 1]是可见区域
重点看[-1, 1]这个区间, 其他两个的View都已经看不到了~~
假设现在ViewPager在A页现在滑出B页,则:
A页的position变化就是(0, -1]
B页的position变化就是[1, 0]
@Override
public void transformPage(View page, float position) {
// 左边看不见得到页面
Log.e("what",position+"");
if(position<-1){
page.setRotation(0);
}else if(position <= 1){//从右往左滑的
// 可见范围的左半场
if(position < 0){
mRot = (ROT_MAX * position);
page.setPivotX(page.getMeasuredWidth()*0.5f);
page.setPivotY(page.getMeasuredHeight());
page.setRotation(mRot);
}else {
mRot = (ROT_MAX * position);
// 设置View的旋转点
page.setPivotX(page.getMeasuredWidth()*0.5f);
page.setPivotY(page.getMeasuredHeight());
page.setRotation(mRot);
}
}else {
page.setRotation(0);
}
}
}
关于ViewPager的无限轮播问题
现在网上流传者两种方法实现ViewPager的无限轮播。一种就是将view的尺寸增加2,而另一种方法就是将getConut设置为一个很大的值。
第一种方法:假设原始的程序有5个,那么设置ViewPager的个数为7个,就是5123451,用
addOnPageChangeListener
进行监听,当滑动View view1 = LayoutInflater.from(this).inflate(R.layout.view1, null, false); View view2 = LayoutInflater.from(this).inflate(R.layout.view2, null, false); View view3 = LayoutInflater.from(this).inflate(R.layout.view3, null, false); View view4 = LayoutInflater.from(this).inflate(R.layout.view4, null, false); View view5 = LayoutInflater.from(this).inflate(R.layout.view5, null, false); View view6 = LayoutInflater.from(this).inflate(R.layout.view1, null, false); View view7 = LayoutInflater.from(this).inflate(R.layout.view5, null, false); mList.add(view1); mList.add(view2); mList.add(view3); mList.add(view4); mList.add(view5); mList3.addAll(mList); mList3.add(0,view7); mList3.add(view6); @Override public void onPageSelected(int position) { Localposition = position; 动画效果略差 所以选择设置最大值 向恶势力低头 if (mList.size() > 1) { //多于1,才会循环跳转 if (position < 1) { //首位之前,跳转到末尾(N) position = mList.size(); advpager.setCurrentItem(position, false); } else if (position > mList.size()) { //末位之后,跳转到首位(1). advpager.setCurrentItem(1, false);//false:不显示跳转过程的动画 } } }
但是动画最后一页到第一页的动画切换效果十分不好因此不使用这个。
- 第二种效果就是设置一个十分大的值但是在调用
advpager.setCurrentItem(n);
这个方法会出现性能问题。但是动画的切换流畅,于是我就放弃了第一种的方法。选择这个方法由于大部分需求都是不会使用到setCurrentItem
的。
代码如下
设置一个很大的值
@Override
public int getCount() {
// return mList3.size();
return 1000;
}
使用除余的方法获取
@Override
public Object instantiateItem(ViewGroup container, int position) {
// container.addView(mList.get(position % mList.size()));
// return mList.get(position % mList.size());
container.addView(mList3.get(position));
return mList3.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// container.removeView(mList.get(position % mList.size()));
container.removeView(mList3.get(position));
}
最后将其设置到中间的值advpager.setCurrentItem(500);
效果就大功告成了。
https://github.com/androidjiasheng/ViewPager_Demo2
参考: