web-dev-qa-db-ja.com

PagerAdapterでの循環スクロールの実装

アプリで新聞のページを表示するための水平スワイプに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);

    }

私のコード(該当する場合)の提案/変更を教えてください。前もって感謝します。

14

これは、onPageSelectedOnPageChangeListenerメソッドをオーバーライドすることで実現できます。この順序で3つのページがあると考えてください_A<->B<->C_。目標は、Cから右にスクロールするとAに到達することであり、同様にAから左にスクロールするとCに到達することです。

これを行うには、5ページ(3 + 2)になるように定義し、次のようにページを整理します。

C _<->A<->B<->C<->_A

ここで、onPageSelectedメソッドで、位置が_0_かどうかを確認し、_3_(getCount()-2)に変更し、位置が_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);
_
21
Arash

円形の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;
    }

}
8
efeyc

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);
                }
            }
        }

    });
4
arvola

これを試して

((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) {}
0
D-D

まあこれは助けた

 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の answer でした

0
Daksh Gargas

私はそれをこのように使用しました、アダプター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);
            }
        }
    });
0
Atul Vasudev A