用ViewPager偏移看到下一页部分内容
# 【Android实战】用ViewPager偏移看到下一页部分内容
http://www.voidcn.com/article/p-zhcdoykj-xn.html
机顶盒项目有个需求,在TV选项下,要求第一页显示节目时,能看到第二页部分内容(也就是图中最右边有黑色遮罩层的那些是第二页的内容):
当向右翻页时,第二页的内容滑到最左边,且第三页的部分内容显示在最右边。
这个项目我是用ViewPager实现滑页的,现在来针对上面的需求进行讲解如何实现。
# 1.准备工作
为此我新建了个简单的项目,用一个ViewPager包裹4个View,每个View给它一个不一样的背景色,并给ViewPager加上适配器(Adapter)。
准备工作就做好了(以下基础代码可跳过)
public void init() {
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
View v1 = new View(this);
View v2 = new View(this);
View v3 = new View(this);
View v4 = new View(this);
v1.setBackgroundColor(Color.parseColor("#aaabcdef"));
v2.setBackgroundColor(Color.parseColor("#aa000a00"));
v3.setBackgroundColor(Color.parseColor("#aaabc000"));
v4.setBackgroundColor(Color.parseColor("#aa000000"));
List<View> views = new ArrayList<View>();
views.add(v1);
views.add(v2);
views.add(v3);
views.add(v4);
viewPager.setAdapter(new AZPagerAdapter(views));
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
AZPagerAdapter的实现是比较常规的优化方法:“显示”就把View加载到父控件,“不显示”就从父控件中移除。
注:这里用“显示”和“不显示”表述不太确切,因为ViewPager默认会多加载前一页(-1页)和后一页(1页)作为缓存页,缓存页没有显示时也会加载到父控件且不会被移除,当缓存页移到-2页或2页时才会被移除。
public class AZPagerAdapter extends PagerAdapter {
protected List<View> views;
public AZPagerAdapter(List<View> viewList) {
views = viewList;
}
@Override
public int getCount() {
return views.size();
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
return views.get(position);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
现在的效果:
# 2.用PageTransformer来改变ViewPager的切换动画
ViewPager有个方法叫做:
setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) 用于设置ViewPager切换时的动画效果。
这里我们只要自定义一个PageTransformer来实现我们需要的动画偏移效果就好了!
public class ScrollOffsetTransformer implements PageTransformer {
/** * position参数指明给定页面相对于屏幕中心的位置。它是一个动态属性,会随着页面的滚动而改变。 * 当一个页面(page)填充整个屏幕时,positoin值为0; * 当一个页面(page)刚刚离开屏幕右(左)侧时,position值为1(-1); * 当两个页面分别滚动到一半时,其中一个页面是-0.5,另一个页面是0.5。 * 基于屏幕上页面的位置,通过诸如setAlpha()、setTranslationX()或setScaleY()方法来设置页面的属性,创建自定义的滑动动画。 */
@Override
public void transformPage(View page, float position) {
if (position > 0) {
//右侧的缓存页往左偏移100
page.setTranslationX(-100 * position);
}
}
}
2
3
4
5
6
7
8
9
10
然后在init()
方法中最后加上
viewPager.setPageTransformer(true, new ScrollOffsetTransformer());
看下效果:
已经可以看到后面一页内容的会偏移到前面一页来(背景色都用了半透明可以看到有叠加部分)!
不过有个问题,就是翻页(1页到0位置)过程中,原本处于2页的view要等到1页完全到0位置后才会突然显示(加载)出来(不是逐渐增加偏移量出来的)。这个原因其实就是刚刚讲Adapter的时候说的,ViewPager默认缓存3页(前页【-1页
】,当前页【0页
】,后页【1页
】),而2页要等到1页到0位置后才会开始加载,(1页到0位置后变为0页,原来的0页变为-1页,原来的-1页被销毁)。
# 3.通过setOffscreenPageLimit(int limit)来改变缓存页数
解决上面遗留的问题也非常简单,就是改变ViewPager的默认缓存页数,使得它多缓存一页(2页)。
ViewPager有个方法叫做:
setOffscreenPageLimit(int limit) 用于设置ViewPager两边(左边和右边)各缓存的页数,默认是1,即左边和右边各缓存1页。
在init()
方法最后再加上一句:
//左右各多加载2页(默认1页)
viewPager.setOffscreenPageLimit(2);
2
看下最后效果:
大功告成!现在就平滑多了!
# 4.彩蛋
把ScrollOffsetTransformer里面稍微改一下,去掉条件判断后
public class ScrollOffsetTransformer implements PageTransformer {
@Override
public void transformPage(View page, float position) {
// if (position > 0) {
page.setTranslationX(-100 * position);
// }
}
}
2
3
4
5
6
7
8
前后都偏移啦!可以开发脑洞想一下用在有趣的地方!
源码地址:[https://github.com/Xieyupeng520/TestViewPager](javascript:void())