开源控件JazzyViewPager分析、扩展(支持循环)
2016-08-09 15:43
351 查看
JazzyViewPager是一个支持多种动画效果的ViewPager,年头有点长了,出的那会我还没开始学Java。
项目下载地址:https://github.com/jfeinstein10/JazzyViewPager
在工作中,有个ViewPager的地方我想加进JazzyViewPager的Tablet效果,来使图像切换变得有趣一些。同时要使JazzyViewPager支持循环轮播。
支持循环的方法见我上一篇文章:http://blog.csdn.net/u014137988/article/details/52101022
然后开始的效果是这样的:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/01/d8eb6887087800507a81f14aaf88eca0)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/01/38df4b5613d3e849a7e74cb64e6435ca)
解释一下:
左边:
单纯的支持循环轮播。然后再循环时(最后1张跳转到第1张),在图像的右边会出现下一张图像的边缘。同样,第1张左滑挑战到最后1张,图像的左边会出现下一张图像的边缘。
右边:
点击ViewPager后查看大图,大图同样支持轮播,在大图界面退出时,JazzyViewPager通过setCurrentItem方法,使JazzyViewPager和大图的当前图片保持一致。setCurrentItem()会导致当前图像变形。
问题已经出现了,先来看看JazzyViewPager的实现,因为我只用了Tablet效果,因此在这里只分析一下Tablet效果是实现。
找到JazzyViewPager类中的onPageScrolled方法,简单起见此处省略和Tablet无关的代码。
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
/*确定ViewPager的滚动状态,
* IDLE,
* GOING_LEFT,
* GOING_RIGHT
*/
if (mState == State.IDLE && positionOffset > 0) {
oldPage = getCurrentItem();
mState = position == oldPage ? State.GOING_RIGHT : State.GOING_LEFT;
}
boolean goingRight = position == oldPage;
if (mState == State.GOING_RIGHT && !goingRight)
mState = State.GOING_LEFT;
else if (mState == State.GOING_LEFT && goingRight)
mState = State.GOING_RIGHT;
float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);
/*
*动画效果
*/
if (mFadeEnabled)
animateFade(mLeft, mRight, effectOffset);
if (mOutlineEnabled)
animateOutline(mLeft, mRight);
switch (mEffect) {
……
case Tablet:
animateTablet(mLeft, mRight, effectOffset);
break;
……
}
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (effectOffset == 0) {
disableHardwareLayer();
mState = State.IDLE;
}
}
动画效果就是这个方法中调用的,animateTablet()。这个方法做了2件事,1是确定滑动状态,2是调用动画效果。
然后来回想一下之前的错误,都发生在setCurrentItem()的时候,这个时候可没有调用onPageScrolled方法,自然没有调用动画。
对症下药,setCurrentItem()导致当前图像变形的解决办法就是重写setCurrentItem,在里面手动去调相应的动画效果。
代码如下:
@Override
public void setCurrentItem(int position){
setCurrentItem(position, true);
}
@Override
public void setCurrentItem(int position, boolean falg){
super.setCurrentItem(position, falg);
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);
if (mFadeEnabled)
animateFade(mLeft, mRight, 0);
if (mOutlineEnabled)
animateOutline(mLeft, mRight);
switch (mEffect) {
case Tablet:
animateTablet(mLeft, mRight, 0);
break;
}
disableHardwareLayer();
// mState = State.IDLE;
}
然后分析另外一个问题,图像的左边/右边会短暂出现下一张图片的边缘。
还是看onPageScrolled方法,这里面只对mLeft和mRight两个View做了处理。
而只漏出边缘的那个View,要么是Left的Left,要么是Right的Right,压根没它什么事情。
也正因为如此,边缘只出现一下就消失,因为很快Right就变成了Left,Right的Right变成了Right。
所以这个问题很好处理,不显示Left的Left和Right的Right就好了。只要不进行预加载就可以了。
修改后的效果是这样的,完全符合原来的预期效果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/01/58e03829cbf61985065bb4b510124e77)
最后提一下:
看看JazzyViewPager里面的View是怎样存储和获取的:
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);看到findViewFromObject方法里面
<span style="white-space:pre"> </span>public View findViewFromObject(int position) {
Object o = mObjs.get(Integer.valueOf(position));
if (o == null) {
return null;
}
PagerAdapter a = getAdapter();
View v;
for (int i = 0; i < getChildCount(); i++) {
v = getChildAt(i);
if (a.isViewFromObject(v, o))
return v;
}
return null;
}其中mObjs是一个HashMap,它的值可以通过setObjectForPosition来设置。
private HashMap<Integer, Object> mObjs = new LinkedHashMap<Integer, Object>();
public void setObjectForPosition(Object obj, int position) {
mObjs.put(Integer.valueOf(position), obj);
}从这两处我们可以看出,JazzyViewPager可以实现在同个ViewPager中展示多种不同的View。
只需要在PagerAdapter的instantiateItem中去根据Position做处理就好了。
项目下载地址:https://github.com/jfeinstein10/JazzyViewPager
在工作中,有个ViewPager的地方我想加进JazzyViewPager的Tablet效果,来使图像切换变得有趣一些。同时要使JazzyViewPager支持循环轮播。
支持循环的方法见我上一篇文章:http://blog.csdn.net/u014137988/article/details/52101022
然后开始的效果是这样的:
解释一下:
左边:
单纯的支持循环轮播。然后再循环时(最后1张跳转到第1张),在图像的右边会出现下一张图像的边缘。同样,第1张左滑挑战到最后1张,图像的左边会出现下一张图像的边缘。
右边:
点击ViewPager后查看大图,大图同样支持轮播,在大图界面退出时,JazzyViewPager通过setCurrentItem方法,使JazzyViewPager和大图的当前图片保持一致。setCurrentItem()会导致当前图像变形。
问题已经出现了,先来看看JazzyViewPager的实现,因为我只用了Tablet效果,因此在这里只分析一下Tablet效果是实现。
找到JazzyViewPager类中的onPageScrolled方法,简单起见此处省略和Tablet无关的代码。
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
/*确定ViewPager的滚动状态,
* IDLE,
* GOING_LEFT,
* GOING_RIGHT
*/
if (mState == State.IDLE && positionOffset > 0) {
oldPage = getCurrentItem();
mState = position == oldPage ? State.GOING_RIGHT : State.GOING_LEFT;
}
boolean goingRight = position == oldPage;
if (mState == State.GOING_RIGHT && !goingRight)
mState = State.GOING_LEFT;
else if (mState == State.GOING_LEFT && goingRight)
mState = State.GOING_RIGHT;
float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);
/*
*动画效果
*/
if (mFadeEnabled)
animateFade(mLeft, mRight, effectOffset);
if (mOutlineEnabled)
animateOutline(mLeft, mRight);
switch (mEffect) {
……
case Tablet:
animateTablet(mLeft, mRight, effectOffset);
break;
……
}
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (effectOffset == 0) {
disableHardwareLayer();
mState = State.IDLE;
}
}
动画效果就是这个方法中调用的,animateTablet()。这个方法做了2件事,1是确定滑动状态,2是调用动画效果。
然后来回想一下之前的错误,都发生在setCurrentItem()的时候,这个时候可没有调用onPageScrolled方法,自然没有调用动画。
对症下药,setCurrentItem()导致当前图像变形的解决办法就是重写setCurrentItem,在里面手动去调相应的动画效果。
代码如下:
@Override
public void setCurrentItem(int position){
setCurrentItem(position, true);
}
@Override
public void setCurrentItem(int position, boolean falg){
super.setCurrentItem(position, falg);
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);
if (mFadeEnabled)
animateFade(mLeft, mRight, 0);
if (mOutlineEnabled)
animateOutline(mLeft, mRight);
switch (mEffect) {
case Tablet:
animateTablet(mLeft, mRight, 0);
break;
}
disableHardwareLayer();
// mState = State.IDLE;
}
然后分析另外一个问题,图像的左边/右边会短暂出现下一张图片的边缘。
还是看onPageScrolled方法,这里面只对mLeft和mRight两个View做了处理。
而只漏出边缘的那个View,要么是Left的Left,要么是Right的Right,压根没它什么事情。
也正因为如此,边缘只出现一下就消失,因为很快Right就变成了Left,Right的Right变成了Right。
所以这个问题很好处理,不显示Left的Left和Right的Right就好了。只要不进行预加载就可以了。
修改后的效果是这样的,完全符合原来的预期效果:
最后提一下:
看看JazzyViewPager里面的View是怎样存储和获取的:
mLeft = findViewFromObject(position);
mRight = findViewFromObject(position+1);看到findViewFromObject方法里面
<span style="white-space:pre"> </span>public View findViewFromObject(int position) {
Object o = mObjs.get(Integer.valueOf(position));
if (o == null) {
return null;
}
PagerAdapter a = getAdapter();
View v;
for (int i = 0; i < getChildCount(); i++) {
v = getChildAt(i);
if (a.isViewFromObject(v, o))
return v;
}
return null;
}其中mObjs是一个HashMap,它的值可以通过setObjectForPosition来设置。
private HashMap<Integer, Object> mObjs = new LinkedHashMap<Integer, Object>();
public void setObjectForPosition(Object obj, int position) {
mObjs.put(Integer.valueOf(position), obj);
}从这两处我们可以看出,JazzyViewPager可以实现在同个ViewPager中展示多种不同的View。
只需要在PagerAdapter的instantiateItem中去根据Position做处理就好了。
相关文章推荐
- 扩展ViewFlow避免和ViewPager滑动冲突,同时支持无限循环,并完美和CircleFlowIndicator结合
- cocos2dx - 控件扩展之pageview循环显示
- 介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView
- Android开源库集合(控件)RecycleView、高亮控件引导、状态栏(StatusBar)、下拉刷新、ViewPager、TextView、手势锁/锁屏解锁、菜单、图表、SearchView
- 用开源项目JazzyViewPager实现ViewPager切换动画
- 开源控件ViewPagerIndicator的使用
- 介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView
- Android从零开搞系列:自定义View(5)基本的自定义ViewPager指示器+开源项目分析(下)
- [Phonegap+Sencha Touch] 移动开发48 扩展的NavigationView控件,支持根据不同的View显示不同的顶栏按钮、不同的屏幕方向,增加视图缓存机制
- 开源控件ViewPagerIndicator的使用
- Android 开源组件无限循环ViewPager
- 开源项目 无限循环ViewPager InfiniteViewPager 分析(二)
- JazzyViewPager开源项目的简析及使用
- Android开源控件ViewPager Indicator的使用方法
- 用开源项目JazzyViewPager实现ViewPager切换动画
- 开源项目ViewPagerIndicator源码分析
- android studio 项目引入viewpagerindicator开源控件
- viewpager布局复用中FragmentPagerAdapter的坑,源码分析,控件id的一些思考
- Android开源控件ViewPager Indicator的使用方法
- Android从零开搞系列:自定义View(4)基本的自定义ViewPager指示器+开源项目分析(上)