您的位置:首页 > 其它

开源控件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

然后开始的效果是这样的:


                                


解释一下:

左边:

单纯的支持循环轮播。然后再循环时(最后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做处理就好了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐