Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
237 views
in Technique[技术] by (71.8m points)

android - How to do circular scrolling on ViewPager?

I would like to set my ViewPager to do circular scrolling. I want the first page to be able to scroll to page 2 AND the last page. And I would like my last page to scroll to [last page -1] AND the first page. I have made an attempt, although I am not sure when to call the method I have created. There does not seem to be a method in ViewPager that handles this sort of thing, so I created the below.

    public ViewPagerAdapter(final ViewPager pager, int... pageIDs) {
        super();
        int actualNoOfIDs = pageIDs.length;
        count = actualNoOfIDs + 2;
        Log.d(TAG, "actualNoOfIDs: " + actualNoOfIDs +
                "count: " + count);

        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];

        Log.d(TAG, "actualNoOfIDs#2: " + actualNoOfIDs +
                "count#2: " + count);
        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 onPageScrollStateChanged(int state) {
                // TODO Auto-generated method stub
                Log.d(TAG, "onPageScrollStateChanged()");
//              if (state == ViewPager.SCROLL_STATE_IDLE) { 
//                  int pageCount = getCount(); 
//                  int currentItem = pager.getCurrentItem(); 
//                  if (currentItem == 0) { 
//                      pager.setCurrentItem(pageCount - 2, false); 
//                  } else if (currentItem == pageCount - 1) { 
//                      pager.setCurrentItem(1, false); 
//                  } 
//              } 

            }

            @Override
            public void onPageScrolled(int position, float positionOffset, 
                    int positionOffsetPixels) {
                // TODO Auto-generated method stub
                Log.d(TAG, "onPageScrolled()");

            }
        });
    }

My entire code is sort of lengthy, but if it helps I can post it.

public class ViewPagerAdapter extends PagerAdapter {
    public static String TAG = ViewPagerAdapter.class.getSimpleName();

    private int count;
    private int[] pageIDsArray;

    private TextToSpeech btnTTS;
    private TtsButton tTSBtn;

    String inputTxt;
    Context context;
    View itemView;

    TextView tvNumber; // container for atomic number
    TextView tvSymbol; // container for symbol
    TextView tvWeight; // container for weight
    TextView tvName; // container for name
    TextView tvGroup; // container for group
    TextView tvPeriod; // container for period
    TextView tvBlock; // container for block
    TextView tvFamily; // container for family
    TextView tvColor; // container for color
    TextView tvPhase; // container for phase
    TextView tvMelt; // container for melting point
    TextView tvBoil; // container for boiling point
    TextView tvNeutrons; // container for neutrons
    TextView tvProtons; // container for protons
    TextView tvElectrons; // container for electrons
    TextView tvUrl; // container for electrons

    public ViewPagerAdapter(Context context, List<Integer> arrayAtomicNum, 
            List<String> arrayName, List<String> arraySymbol, List<String> arrayFamily,
            List<String> arrayPhase, List<String> arrayColor, List<Integer> arrayGroup, 
            List<Integer> arrayPeriod, List<String> arrayBlock, List<Integer> arrayProtons,
            List<Integer> arrayNeutrons, List<Integer> arrayElectrons, List<Double> arrayWeight,
            List<Double> arrayMelt, List<Double> arrayBoil, List<String> arrayUrl) {    
        this.context = context;
        ElementStructure.arrayAtomicNum = arrayAtomicNum;
        ElementStructure.arrayName = arrayName;
        ElementStructure.arraySymbol = arraySymbol;
        ElementStructure.arrayFamily = arrayFamily;
        ElementStructure.arrayPhase = arrayPhase;
        ElementStructure.arrayColor = arrayColor;
        ElementStructure.arrayGroup = arrayGroup;
        ElementStructure.arrayPeriod = arrayPeriod;
        ElementStructure.arrayBlock = arrayBlock;
        ElementStructure.arrayProtons = arrayProtons;
        ElementStructure.arrayNeutrons = arrayNeutrons;
        ElementStructure.arrayElectrons = arrayElectrons;
        ElementStructure.arrayWeight = arrayWeight;
        ElementStructure.arrayMelt = arrayMelt;
        ElementStructure.arrayBoil = arrayBoil;
        ElementStructure.arrayUrl = arrayUrl;
    }


    public ViewPagerAdapter(final ViewPager pager, int... pageIDs) {
        super();
        int actualNoOfIDs = pageIDs.length;
        count = actualNoOfIDs + 2;
        Log.d(TAG, "actualNoOfIDs: " + actualNoOfIDs +
                "count: " + count);

        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];

        Log.d(TAG, "actualNoOfIDs#2: " + actualNoOfIDs +
                "count#2: " + count);
        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 onPageScrollStateChanged(int state) {
                // TODO Auto-generated method stub
                Log.d(TAG, "onPageScrollStateChanged()");
//              if (state == ViewPager.SCROLL_STATE_IDLE) { 
//                  int pageCount = getCount(); 
//                  int currentItem = pager.getCurrentItem(); 
//                  if (currentItem == 0) { 
//                      pager.setCurrentItem(pageCount - 2, false); 
//                  } else if (currentItem == pageCount - 1) { 
//                      pager.setCurrentItem(1, false); 
//                  } 
//              } 

            }

            @Override
            public void onPageScrolled(int position, float positionOffset, 
                    int positionOffsetPixels) {
                // TODO Auto-generated method stub
                Log.d(TAG, "onPageScrolled()");

            }
        });
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return ElementStructure.arrayAtomicNum.size();

    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        // TODO Auto-generated method stub
        return view == ((RelativeLayout) object);
    }

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

        LayoutInflater inflater = (LayoutInflater) context
             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        int layoutColorId = ElementStructure.arrayLayoutColor.get(position);

        if (layoutColorId == 1) {
            itemView = inflater.inflate(R.layout.frame_learn_a, container,
                     false);
        } else if (layoutColorId == 2) {
            itemView = inflater.inflate(R.layout.frame_learn_b, container,
                     false);
        } else if (layoutColorId == 3) {
            itemView = inflater.inflate(R.layout.frame_learn_c, container,
                     false);
        } else if (layoutColorId == 4) {
            itemView = inflater.inflate(R.layout.frame_learn_d, container,
                     false);    
        }

        Button btnSpeak = (Button)itemView.findViewById(R.id.btnaudio);

        btnSpeak.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                inputTxt = ElementStructure.arrayName.get(position);
                tTSBtn = new TtsButton(this, inputTxt); 
            }

        });

        // atomic number textView
        tvNumber = (TextView)itemView.findViewById(R.id.metanumber);

        // symbol textView
        tvSymbol = (TextView)itemView.findViewById(R.id.metasymbol);

        // weight textView
        tvWeight = (TextView)itemView.findViewById(R.id.metaweight);

        // name textView
        tvName = (TextView)itemView.findViewById(R.id.metaname);

        // group textView
        tvGroup = (TextView)itemView.findViewById(R.id.metagroup);

        // period textView
        tvPeriod = (TextView)itemView.findViewById(R.id.metaperiod);

        // block textView
        tvBlock = (TextView)itemView.findViewById(R.id.metablock);

        // family textView
        tvFamily = (TextView)itemView.findViewById(R.id.metafamily);

        // color textView
        tvColor = (TextView)itemView.findViewById(R.id.metacolor);

        // phase textView
        tvPhase = (TextView)itemView.findViewById(R.id.metaphase);

        // melting point textView
        tvMelt = (TextView)itemView.findViewById(R.id.metamelt);

        // boiling point textView
        tvBoil = (TextView)itemView.findViewById(R.id.metaboil);

        // neutrons textView
        tvNeutrons = (TextView)itemView.findViewById(R.id.metaneutrons);

        // protons textView
        tvProtons = (TextView)itemView.findViewById(R.id.metaprotons);

        // electrons textView
        tvElectrons = (TextView)itemView.findViewById(R.id.metaelectrons);

        // url textView
        tvUrl = (TextView)itemView.findViewById(R.id.metaurl);

        // capture position and set to the TextViews
        tvNumber.setText(String.valueOf(ElementStructure.arrayAtomicNum.get(position)));
        tvSymbol.setText(ElementStructure.arraySymbol.get(position));
        tvWeight.setText(String.valueOf(ElementStructure.arrayWeight.get(position)));
        tvName.setText(ElementStructure.arrayName.get(position));
        tvPeriod.setText(String.valueOf(ElementStructure.arrayPeriod.get(position)));
        tvBlock.setText(String.valueOf(ElementStructure.arrayBlock.get(position)));
        tvFamily.setText(ElementStructure.arrayFamily.get(position));
        tvColor.setText(ElementStructure.arrayColor.get(position));
        tvPhase.setText(ElementStructure.arrayPhase.get(position));
        tvNeutrons.setText(String.valueOf(ElementStructure.arrayNeutrons.get(position)));
        tvProtons.setText(String.valueOf(ElementStructure.arrayProtons.get(position)));
        tvElectrons.setText(String.valueOf(ElementStructure.arrayElectrons.get(position)));
        tvUrl.setText(ElementStructure.arrayUrl.get(position));

        // capture position, adjust for 0 value cases
        if (ElementStructure.arrayGroup.get(position) == 0) {
            tvGroup.setText("n/a");
        } else {
            tvGroup.setText(String.valueOf(ElementStructure.arrayGroup.get(position)));
        }

        if (ElementStructure.arrayMelt.get(position) == 0) {
            tvMelt.setText("n/a");
        } else {
            tvMelt.setText(String.valueO

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a solution without fake pages and works like a charm:

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

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

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

    @Override
    public void onPageScrollStateChanged(final int state) {
        handleScrollState(state);
        mScrollState = state;
    }

    private void handleScrollState(final int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE && mScrollState == ViewPager.SCROLL_STATE_DRAGGING) {
            setNextItemIfNeeded();
        }
    }

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

    private boolean isScrollStateSettling() {
        return mScrollState == ViewPager.SCROLL_STATE_SETTLING;
    }

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

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

You just have to set it to your ViewPager as onPageChangeListener and that's it:

viewPager.setOnPageChangeListener(new CircularViewPagerHandler(viewPager));

To avoid having this blue shine at the "end" of your ViewPager you should apply this line to your xml where the ViewPager is placed:

android:overScrollMode="never"

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...