14

我正在使用 PagerAdapter 进行水平滑动以在我的应用程序中显示报纸页面。

目前我想在这个应用程序中实现循环滚动。现在我所做的是whenever I am getting on last page I try to set the currentItem to first page该功能适用​​于最后一页到第一页,但问题是我怎样才能从第一页转到最后一页。在这里,我粘贴与 pagerAdapter 和 onPageChangeListener 相关的代码:-

    awesomeAdapter = new AwesomePagerAdapter(awesomePager);
    awesomePager.setAdapter(awesomeAdapter);
    awesomePager.setPageMargin(10);
    awesomePager.setOnPageChangeListener(new OnPageChangeListener() {

        int lastPosition;
        float posOffset = 0;
        @Override
        public void onPageSelected(int position) {
               viewerPage = position;
               CommonLogic.logMessage("Viewer Page:- "+ viewerPage, TAG, Log.VERBOSE);
               posOffset = 0;
        }

        @Override
        public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {
            if (positionOffset == 0 && positionOffsetPixels == 0 && position != 0) {
                    lastPosition = position;
            }

            posOffset -= positionOffset;

            CommonLogic.logMessage(" Position:-  "
                                     + position + " Position Offset:- "                                     + positionOffset
                                        + " Position Offset Variable:-  "
                                        + posOffset
                                        + "  Position Offset Pixels:- "
                                        + positionOffsetPixels
                                        + " Last Position " + lastPosition,
                                        TAG, Log.VERBOSE);

                                CommonLogic.logMessage(" Last Position "
                                        + lastPosition, TAG, Log.VERBOSE);

        }

        @Override
        public void onPageScrollStateChanged(int state) {
                 // To Detect the Last Page & This Sets it to first page.This working fine. 
         if (state == ViewPager.SCROLL_STATE_DRAGGING && viewerPage == (uris.size() - 1)) {
            CommonLogic.logMessage("Scroll State Changed ", TAG,Log.VERBOSE);
            postDelayed(new Runnable() {
               @Override
               public void run() {
                awesomePager.setCurrentItem(0, true);
               }
            }, 200);
        }
// I have also used this to detect whether the user is on first & try to move on last page,but it is not working well.
else if (state == ViewPager.SCROLL_STATE_DRAGGING && (lastPosition == 0 || lastPosition == (uris.size() - 1)) && viewerPage == 0 && posOffset <= 0) {
                                    CommonLogic.logMessage( "Scroll State Changed ", TAG,Log.VERBOSE);
    postDelayed(new Runnable() {
        @Override
        public void run() {
         awesomePager.setCurrentItem((uris.size() - 1), true);
                }
        }, 200);
        } 
}
}
    });

在我的情况下,PagerAdapter 即 AwesomweAdapter 也如下所示:-

private class AwesomePagerAdapter extends PagerAdapter {

    ViewPager pdfContainer;
    DocumentNewView documentNewView;
    CustomViewPager customViewPager;

    public AwesomePagerAdapter(CustomViewPager awesomePager) {
        this.customViewPager = awesomePager;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public int getCount() {
        return uris.size();
    }

    public DocumentNewView addViewAt(int position, DocumentNewView mainView) {
        CommonLogic.logMessage("Position of View:- " + position, TAG,
                Log.VERBOSE);
        pdfContainer.addView(mainView);
        return mainView;
    }

    /**
     * Create the page for the given position. The adapter is responsible
     * for adding the view to the container given here, although it only
     * must ensure this is done by the time it returns from
     * {@link #finishUpdate()}.
     * 
     * @param container
     *            The containing View in which the page will be shown.
     * @param position
     *            The page position to be instantiated.
     * @return Returns an Object representing the new page. This does not
     *         need to be a View, but can be some other container of the
     *         page.
     */
    @Override
    public Object instantiateItem(View collection, int position) {
        CommonLogic
                .logMessage("Instantiate Item Called ", TAG, Log.VERBOSE);

        documentNewView = new DocumentNewView(cxt, display, customViewPager);
        documentNewView.setPdfContext(new PdfContext());
        CodecDocument codecDocument = documentNewView.open(uris
                .get(position));
        documentNewView.renderDocument(codecDocument);
        documentNewView.setMaxZoom(4f);
        documentNewView.setVerticalScrollBarEnabled(true);
        codecDocument = null;
        this.pdfContainer = (ViewPager) collection;
        return addViewAt(position, documentNewView);
     }

    /**
     * Remove a page for the given position. The adapter is responsible for
     * removing the view from its container, although it only must ensure
     * this is done by the time it returns from {@link #finishUpdate()}.
     * 
     * @param container
     *            The containing View from which the page will be removed.
     * @param position
     *            The page position to be removed.
     * @param object
     *            The same object that was returned by
     *            {@link #instantiateItem(View, int)}.
     */
    @Override
    public void destroyItem(View collection, int position, Object view) {
        pdfContainer.removeView((DocumentNewView) view);

    }

    /**
     * Called when the a change in the shown pages has been completed. At
     * this point you must ensure that all of the pages have actually been
     * added or removed from the container as appropriate.
     * 
     * @param container
     *            The containing View which is displaying this adapter's
     *            page views.
     */
    @Override
    public void finishUpdate(View arg0) {
        CommonLogic.logMessage("Finish Update Called ", TAG, Log.VERBOSE);
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void startUpdate(View arg0) {
        CommonLogic.logMessage("State Update Called ", TAG, Log.VERBOSE);
    }

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

    }

请给我任何建议/更改我的代码(如果适用)。提前致谢。

4

6 回答 6

21

我可以通过覆盖onPageSelected. OnPageChangeListener假设您按此顺序有三页A<->B<->CC如果我们从 向右滚动,目标就是到达,如果我们从向左滚动,目标就是A到达。AC

为此,请将您的页面定义为 5 个页面 (3+2),并按如下方式组织页面:

C<->A<->B<->C<->A

现在在onPageSelected方法中,检查如果 position if 0,将其更改为3( getCount()-2),如果 position 是4( getCount()-1),将其更改为1。确保使用以下方法:

setCurrentItem(item, smoothScroll)

这是CircularPagerAdaptor类的完整代码:

package zolender.adapters;

import android.content.Context;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;

public class CircularPagerAdapter extends PagerAdapter{

    private int[] pageIDsArray;
    private int count;

    public CircularPagerAdapter(final ViewPager pager, int... pageIDs) {
        super();
        int actualNoOfIDs = pageIDs.length;
        count = actualNoOfIDs + 2;
        pageIDsArray = new int[count];
        for (int i = 0; i < actualNoOfIDs; i++) {
            pageIDsArray[i + 1] = pageIDs[i];
        }
        pageIDsArray[0] = pageIDs[actualNoOfIDs - 1];
        pageIDsArray[count - 1] = pageIDs[0];

        pager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                int pageCount = getCount();
                if (position == 0){
                    pager.setCurrentItem(pageCount-2,false);
                } else if (position == pageCount-1){
                    pager.setCurrentItem(1,false);
                }
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // TODO Auto-generated method stub
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // TODO Auto-generated method stub
            }
        });
    }

    public int getCount() {
        return count;
    }

    public Object instantiateItem(View container, int position) {
        LayoutInflater inflater = (LayoutInflater) container.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        int pageId = pageIDsArray[position];
        View view = inflater.inflate(pageId, null);
        ((ViewPager) container).addView(view, 0);
        return view;
    }

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

    @Override
    public void finishUpdate(View container) {
        // TODO Auto-generated method stub
    }

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

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        // TODO Auto-generated method stub
    }

    @Override
    public Parcelable saveState() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void startUpdate(View container) {
        // TODO Auto-generated method stub
    }
}

以下是如何使用它:

myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
PagerAdapter adapter = new CircularPagerAdapter(myPager, new int[]{R.layout.farleft, R.layout.left, R.layout.middle, R.layout.right, R.layout.farright});
myPager.setAdapter(adapter);
myPager.setCurrentItem(3);
于 2012-06-07T08:16:53.003 回答
8

我还需要一个圆形 ViewPager。这就是我所做的。我假设您从某个地方获得 pageCount 值。

...
    pager = (ViewPager) findViewById(R.id.pager);
    //Gesture detection
    final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector());
    pager.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    });

    //pagelistener is just for getting selected page
    pager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            selectedPage = position;
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });

这是GestureDetector。从这里复制

    class MyGestureDetector extends SimpleOnGestureListener {

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        int SWIPE_MIN_DISTANCE = Utils.ConvertToPixel(mContext, 50);
        int SWIPE_MAX_OFF_PATH = Utils.ConvertToPixel(mContext, 250);
        int SWIPE_THRESHOLD_VELOCITY = Utils.ConvertToPixel(mContext, 200);

        try {

            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                return false;
            // right to left swipe
            if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE 
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
                    && selectedPage == (pageCount - 1)) {
                pager.setCurrentItem(0);
                return true;
            }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE 
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
                    && selectedPage == 0) {
                pager.setCurrentItem(pageCount - 1);
                return true;
            }
        } catch (Exception e) {
            // nothing
        }
        return false;
    }

}
于 2012-03-07T10:01:13.433 回答
4

扩展Z0lenDer的答案,当使用ViewPager不需要为每个关联视图释放内存的常规时,存储创建的视图而不是布局 ID 更有效。如果想要在切换项目时摆脱任何延迟和闪烁,这是必要的。

使用 时动画也存在问题onPageSelected,因为它不会让幻灯片在切换之前完成。我发现避免这种情况的唯一方法是仅在滚动状态更改为时执行切换,SCROLL_STATE_IDLE并将当前项目设置为onPageSelected.

private int currentPage = 0;

...

    pager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            currentPage = position;
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {
            // TODO Auto-generated method stub
            Log.d(TAG, "onPageScrollStateChanged: " + state);
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                int pageCount = getCount();
                if (currentPage == 0){
                    pager.setCurrentItem(pageCount-2,false);
                } else if (currentPage == pageCount-1){
                    pager.setCurrentItem(1,false);
                }
            }
        }

    });
于 2012-06-18T20:24:54.337 回答
0

尝试这个

((ViewPager) container)
                .setOnPageChangeListener(new OnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        Log.i("TAG", "pos::" + position);

                    }
                    @Override
                    public void onPageScrollStateChanged(int state) {
                        // TODO Auto-generated method stub                            
                           int currentPage = pager.getCurrentItem();
                           Log.i("TAG", "currentPage::" + currentPage);
                           Log.i("TAG", "currentState::" + currentState);
                           Log.i("TAG", "previousState::" + previousState);
                           if (currentPage == 4 || currentPage == 0) {
                            previousState = currentState;
                            currentState = state;
                            if (previousState == 1 && currentState == 0) {
                             pager.setCurrentItem(currentPage == 0 ? 4 : 0);
                            }
                           }

                    }

                    @Override
                    public void onPageScrolled(int arg0, float arg1,
                            int arg2) {
                        // TODO Auto-generated method stub

                    }
                });

        return

这应该放在里面

 @Override
    public Object instantiateItem(final View container, int position) {}
于 2014-05-21T09:59:17.123 回答
0

嗯,这有帮助

 private class CircularViewPagerHandler implements ViewPager.OnPageChangeListener {
    private ViewPager mViewPager;
    private int mCurrentPosition;
    private int mScrollState;
    private int mPreviousPosition;

    public CircularViewPagerHandler(final ViewPager viewPager) {
        mViewPager = viewPager;
    }

    @Override
    public void onPageSelected(final int position) {
        mCurrentPosition = position;
        mPreviousPosition = position-1;
    }

    @Override
    public void onPageScrollStateChanged(final int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            setNextItemIfNeeded();
        }
        mScrollState = state;
    }


    private void setNextItemIfNeeded() {
        if (!isScrollStateSettling()) {
            handleSetNextItem();
        }
    }

    private boolean isScrollStateSettling() {
        return mScrollState == ViewPager.SCROLL_STATE_SETTLING; //indicated page is settling to it's final position
    }

    private void handleSetNextItem() {
        final int lastPosition = mViewPager.getAdapter().getCount() - 1;
        if (mCurrentPosition == 0) {
            mViewPager.setCurrentItem(lastPosition,false);
        } else if (mCurrentPosition == lastPosition) {
            mViewPager.setCurrentItem(0, false);
        }
    }

    @Override
    public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {

    }
}

这是@tobi_b 的回答

于 2017-06-21T07:31:15.603 回答
0

我这样使用它,适配器 0>1>2>3>4>5、0 和 5 中的片段布局是虚拟的

    viewPager.setAdapter(adapter);
    viewPager.setCurrentItem(1, false);        //going to page 1;

    final int[] pagePosition = new int[1];

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            pagePosition[0] = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) { //state changes from 2 to 0 during a swipe

            if (state == 0 && pagePosition[0] == 0){            
                viewPager.setCurrentItem(4, false);
            } else if (state == 0 && pagePosition[0] == 5){
                viewPager.setCurrentItem(1, false);
            }
        }
    });
于 2016-01-13T09:42:27.497 回答