ViewPager.PageTransformer Android

时间:2015-04-25 22:15:54

标签: android android-viewpager

我想做以下事情,

使用ViewLager内ScrollVIew内的GridLayout创建图像网格,假设我有图片页面,第1页是动物,第2页植物等等。我希望能够向上和向下滚动查看图像,第1页上的动物,并使用PageTransformer向右和向左滚动以使用动画更改页面。我还需要按照here所述的方式查看左侧和右侧的页面。现在我完成了所有这些,但触摸事件中存在一些我无法解决的冲突,这就是我需要你帮助的地方。

现在当我使用pager.setPageTransformer(true, new ZoomOutPageTransformer());时,我丢失了ScrollView上下滚动,我得到了很酷的动画。当我不使用它时,除了动画,我得到了我需要的一切,我怎么能得到它们呢?

这是我的主要活动,

public class MainActivity extends Activity {

    PagerContainer mContainer;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContainer = (PagerContainer) findViewById(R.id.pager_container);

        final ViewPager pager = mContainer.getViewPager();
        PagerAdapter adapter = new MyPagerAdapter();
        pager.setAdapter(adapter);
//Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
        pager.setOffscreenPageLimit(adapter.getCount());
//A little space between pages
        pager.setPageMargin(20);

//If hardware acceleration is enabled, you should also remove
// clipping on the pager for its children.
         pager.setClipChildren(false);
         pager.setPageTransformer(true, new ZoomOutPageTransformer());

    }

    //Nothing special about this adapter, just throwing up colored views for demo
    private class MyPagerAdapter extends PagerAdapter {

        @Override
        public Object instantiateItem(ViewGroup container, int position) {


            LinearLayout layout = new LinearLayout(container.getContext());
            layout.setOrientation(LinearLayout.VERTICAL);
            layout.setLayoutParams(new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));

            ScrollView sv=new ScrollView(container.getContext());

            GridLayout gl = new GridLayout(container.getContext());
            gl.setLayoutParams(new ViewGroup.LayoutParams ( ViewGroup.LayoutParams.MATCH_PARENT,  ViewGroup.LayoutParams.MATCH_PARENT));
            gl.setOrientation(GridLayout.HORIZONTAL);
            gl.setColumnCount(3);
            gl.setRowCount(3);

            for(int i=0;i<9;i++) {
                ImageView imgView = new ImageView(container.getContext());
                imgView.setImageResource(R.drawable.ic_launcher);
                gl.addView( imgView);
            }

            sv.setVerticalScrollBarEnabled(false);

            sv.addView(gl);
            container.addView(sv);


            return sv;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View)object);
        }

        @Override
        public int getCount() {
            return 5;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return (view == object);
        }
    }
}

我的页面转换器就是这个,

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {

    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(MIN_ALPHA);
            view.setScaleX(MIN_SCALE);
            view.setScaleY(MIN_SCALE);

        } else if (position <= 1) { // [-1,1]
            // Modify the default slide transition to shrink the page as well
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA +  (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
            view.clearAnimation();

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(MIN_ALPHA);
            view.setScaleX(MIN_SCALE);
            view.setScaleY(MIN_SCALE);

        }
    }
}

最后我的页面容器就是这个,

public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener {

    private ViewPager mPager;
    boolean mNeedsRedraw = false;

    public PagerContainer(Context context) {
        super(context);
        init();
    }

    public PagerContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PagerContainer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
//Disable clipping of children so non-selected pages are visible
        setClipChildren(false);

//Child clipping doesn't work with hardware acceleration in Android 3.x/4.x
//You need to set this value here if using hardware acceleration in an
// application targeted at these releases.
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    protected void onFinishInflate() {
        try {
            mPager = (ViewPager) getChildAt(0);
            mPager.setOnPageChangeListener(this);
        } catch (Exception e) {
            throw new IllegalStateException("The root child of PagerContainer must be a ViewPager");
        }
    }

    public ViewPager getViewPager() {
        return mPager;
    }

    private Point mCenter = new Point();
    private Point mInitialTouch = new Point();

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mCenter.x = w / 2;
        mCenter.y = h / 2;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
//We capture any touches not already handled by the ViewPager
// to implement scrolling from a touch outside the pager bounds.
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mInitialTouch.x = (int)ev.getX();
                mInitialTouch.y = (int)ev.getY();
            default:
                ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y);
                break;
        }

        return mPager.dispatchTouchEvent(ev);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Force the container to redraw on scrolling.
//Without this the outer pages render initially and then stay static
        if (mNeedsRedraw) invalidate();
    }

    @Override
    public void onPageSelected(int position) { }

    @Override
    public void onPageScrollStateChanged(int state) {
        mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE);
    }
}

1 个答案:

答案 0 :(得分:1)

我在查看this之后发现了这个问题,我认为你不需要使用这个pager.setPageTransformer(true, new ZoomOutPageTransformer());,并从我之前提到的链接中复制一些东西,然后放{ {1}}作为容器中的函数,因为您将在其中进行转换,最终代码如下所示。

ZoomOutPageTransformer

仅使用上面的PagerContainer和MainActivity,并且不要使用forger来禁用它上面的setPageTransformer。