一、效果图
ezgif.com-video-to-gif.gif
二、简单分析
1、要保证view垂直滚动
2、数据集合不定
3、view的缓存/复用
三、设计
简易的效仿经典的ListView组件,适配器处理数据,view显示布局。
1、自定义YverticalView继承FrameLayout,作为滚动view的父布局,view的滚动可选择scroll和值动画,值动画使用较为简便
2、初始化
可初始化值动画,设置插值器,匀速滑动
public void init() {
if (mValueAnimator == null) {
mValueAnimator = ValueAnimator.ofFloat(0, 1f);
}
mValueAnimator.setDuration(mDuration);
mValueAnimator.setInterpolator(new LinearInterpolator());
}
3、加载子view过程判断数据的个数:
=0:不加载view
=1:加载一个view
当>1:加载两个view
因为垂直滚动过程最多同时显示2条子view,即使N条数据仅加载两个子view。这点ListView和RecyclerView中使用的ViewHolder缓存item布局中的view,防止多次加载引发内存溢出。
4、本自定义YverticalView直接强制初始化两个mFirstview, mSecondView作为滚动的子view
当数据>1时,add子view的时候,保证mSecondView位于mFirstview下方为YverticalView的高度,同时开启动画
else if (mAdapter.getCount() > 1) {
mCorrentState = STATE_VERTICAL;
mFirstview = mAdapter.getLayout(this);
mSecondView = mAdapter.getLayout(this);
FrameLayout.LayoutParams layoutParams = (LayoutParams)
mSecondView.getLayoutParams();
layoutParams.setMargins(0, mHeight, 0, 0);
addView(mFirstview);
addView(mSecondView);
initAnim();
postDelayed(animRunnable, mDuration);
}
5、动画过程中通过适配器绑定view和data
public YverticalView initAnim() {
mAdapter.bindView(mPosition % mAdapter.getCount(), mFirstview);
mAdapter.bindView((mPosition + 1) % mAdapter.getCount(), mSecondView);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimValue = (float) animation.getAnimatedValue();
scrollAnim();
invalidate();
}
});
mValueAnimator.start();
return this;
}
6、使用post重复执行值动画
private AnimRunnable animRunnable = new AnimRunnable();
private class AnimRunnable implements Runnable {
@Override
public void run() {
mPosition++;
mValueAnimator.cancel();
initAnim();
postDelayed(animRunnable, mDuration);
}
}
7、关于适配器
两点作用:
加载item布局,即YverticalView中的mFirstview, mSecondView
根据子view的滚动过程,绑定数据
核心:
public abstract View setLayout(YverticalView yverticalView);
public abstract void bindView(int position, View view);
public View getLayout(YverticalView yverticalView) {
return setLayout(yverticalView);
}
8、最后,在YverticalView回收的时候不要忘记关闭值动画:
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopScroll();
}
public void stopScroll() {
if (mValueAnimator != null) {
mValueAnimator.cancel();
}
}
四、demo
自定义垂直滚动demo