The main idea of customization is to inherit the viewpager, then rewrite the swapTouchEvent method to modify the handover gesture, instead of sliding up and down to trigger the handover event.
public class VerticalViewPager extends ViewPager { private boolean isPagingEnabled = true; public VerticalViewPager(Context context) { super(context); } public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); } private MotionEvent swapTouchEvent(MotionEvent event) { float width = getWidth(); float height = getHeight(); event.setLocation((event.getY() / height) * width, (event.getX() / width) * height); return event; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return super.onInterceptTouchEvent(swapTouchEvent(MotionEvent.obtain(event)))&&this.isPagingEnabled; } @Override public boolean onTouchEvent(MotionEvent ev) { return super.onTouchEvent(swapTouchEvent(MotionEvent.obtain(ev)))&&this.isPagingEnabled; } public void setPagingEnabled(boolean b) { this.isPagingEnabled = b; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = 0; for(int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); if(h > height) height = h; } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
The height of the viewpager is determined by the height of the largest sub-item, and the sliding can be set by setPagingEnabled. By default, sliding is allowed.
The above is just to set the switching gesture. The switching animation needs to be reset.
public class VerticalTransformer implements ViewPager.PageTransformer{ @Override public void transformPage(View view, float position) { view.setTranslationX(view.getWidth() * -position); float yPosition = position * view.getHeight(); view.setTranslationY(yPosition); } }
Originally, it was switched in the x direction, but when set to - position, it canceled out. When switched in the y direction, it can set transparency, if necessary.
Set up
mVerticalViewPager.setPageTransformer(true, new VerticalTransformer());
Is it easy to complete a vertically switched viewpager with the above settings?
Here is the complete call
private void initVerticalPager() { if (mVerticalViewPager == null) { mVerticalViewPager = (VerticalViewPager) getRootView().findViewById(R.id.vertical_viewpager); mVerticalPagerAdapter = new VerticalPagerAdapter(); mVerticalViewPager.setAdapter(mVerticalPagerAdapter); mVerticalViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER); mVerticalViewPager.setPageTransformer(true, new VerticalTransformer()); } else { mVerticalPagerAdapter.notifyDataSetChanged(); } }
Adapter
private class VerticalPagerAdapter extends PagerAdapter { @Override public int getCount() { return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { View view = null; view = View.inflate(mContext, R.layout.weiget_main_information, null); switch(position%count){ case 0: view = ...; break; case 1: ... } container.addView(view); return view; } }
We set up a pseudo-infinite loop viewpager here, so we put back the maximum value of the shaping in the getCount method. In fact, it is almost impossible for us to achieve this maximum value by sliding between app s. As for the loop, we instantiate the new view in instantiate Item according to the requirement, and instantiate the new view every time. And initialize the data without worrying about generating too much garbage, because the view is removed from the destroyItem method and waiting for gc to recycle
private static int SWITCH_TIME = 30*1000; public void startSwitchTask() { if (handler == null) { handler = new Handler(); } handler.removeCallbacksAndMessages(null); handler.postDelayed(runnable,SWITCH_TIME); } public void stopSwitchTask() { if (handler != null) { handler.removeCallbacksAndMessages(null); handler = null; } } private Runnable runnable = new Runnable( ) { public void run ( ) { doSwitch(); handler.postDelayed(this,SWITCH_TIME); } }; private void doSwitch() { if(mVerticalViewPager ==null){ return; } mVerticalViewPager.setCurrentItem(mVerticalViewPager.getCurrentItem()+1); }
The ingenuity of timing is
Runnable is triggered by handler.postDelayed, then business is completed in runnable, and handler.postDelayed method is triggered. This method needs to be valid within the action declaration cycle because of the use of handler. If action is recycled, stopSwitchTask method needs to be invoked in onDestroy method to avoid memory leak.
The doSwitch method switches viewpager, position increases, and no additional variables need to be maintained.