时间:2021-11-12 09:16:33 | 栏目:Android代码 | 点击:次
传统的ViewPager做循环滚动有两种思路。
一种是设置count为Integer.MAX,然后根据index对实际数量取模
一种是在开头在开头添加end,在末尾添加start。简单的说就是多两个,滑动到这两个的时候直接setCurrentItem到真正的位置。
在观察pdd的拼单的循环滚动的时候,想到几种实现方式。
1、通过Recyclerview,同样跟ViewPager做循环滚动的思路类似,多一点要拦截掉所有的触摸事件。但是这种方式的话无法像pdd的效果那样设置进入和出去的动画。
2、通过改造VerticalViewpager的形式,应该也是可以的,但是感觉比较麻烦。
3、通过自定义的方式实现。(原本以为挺简单的,实现了下,代码不多但是有些小细节需要注意下。)
我选择了自定义的这里只是一个demo,提供一种思路。
最核心的就是上面的item滑出屏幕的时候将它remove掉然后再加到自定义的ViewGroup的末尾。
public class LoopView extends ViewGroup { private static final String TAG = "LoopView"; private float dis; private ObjectAnimator animator; private int currentIndex = 0; private Handler handler = new Handler(Looper.getMainLooper()); public LoopView(Context context) { super(context); init(); } public LoopView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LoopView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } void init() { View view1 = new View(getContext()); view1.setTag("gray"); view1.setBackgroundColor(Color.GRAY); LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, 200); addView(view1, layoutParams); View view2 = new View(getContext()); view2.setTag("red"); view2.setBackgroundColor(Color.RED); LayoutParams layoutParams1 = new LayoutParams(LayoutParams.MATCH_PARENT, 200); addView(view2, layoutParams1); View view3 = new View(getContext()); view3.setTag("green"); view3.setBackgroundColor(Color.GREEN); LayoutParams layoutParams2 = new LayoutParams(LayoutParams.MATCH_PARENT, 200); addView(view3, layoutParams2); animator = ObjectAnimator.ofFloat(this, "dis", 0, 1); animator.setDuration(2000); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { currentIndex++; View first = getChildAt(0); removeView(first); addView(first); handler.postDelayed(new Runnable() { @Override public void run() { animator.clone().start(); } }, 3000); } }); } public void start() { animator.start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measureChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(200, MeasureSpec.EXACTLY)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int top = currentIndex * getMeasuredHeight(); for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); childAt.layout(l, top, r, top + childAt.getMeasuredHeight()); top += childAt.getMeasuredHeight(); } } public float getDis() { return dis; } public void setDis(float dis) { this.dis = dis; float disY = dis * getHeight(); scrollTo(0, (int) (currentIndex * getHeight() + disY)); } }
需要注意的就是onLayout的时候对于top的取值。