【问题标题】:How to do circular scrolling on ViewPager?如何在 ViewPager 上进行循环滚动?
【发布时间】:2014-01-26 20:20:32
【问题描述】:

我想将我的 ViewPager 设置为循环滚动。我希望第一页能够滚动到第 2 页和最后一页。我希望我的最后一页滚动到 [最后一页 -1] 和第一页。我已经尝试过了,虽然我不确定何时调用我创建的方法。 ViewPager 中似乎没有处理此类事情的方法,所以我创建了以下内容。

    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()");

            }
        });
    }

我的整个代码有点长,但如果有帮助,我可以发布它。

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.valueOf(ElementStructure.arrayMelt.get(position)));
        }

        if (ElementStructure.arrayBoil.get(position) == 0) {
            tvBoil.setText("n/a");
        } else {
            tvBoil.setText(String.valueOf(ElementStructure.arrayBoil.get(position)));
        }

        // add fragments to container (ViewPager)
        ((ViewPager) container).addView(itemView);
        return itemView;

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Log.d(TAG, "destroyItem()");
        // remove fragments from container (ViewPager)
        ((ViewPager) container).removeView((RelativeLayout) object);
    }


    @Override
    public void finishUpdate(View container) {
        // TODO Auto-generated method stub
        Log.d(TAG, "finishUpdate()");
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        // TODO Auto-generated method stub
        Log.d(TAG, "restoreState()");
    }

    @Override
    public Parcelable saveState() {
        // TODO Auto-generated method stub
        Log.d(TAG, "saveState()");
        return null;
    }

    @Override
    public void startUpdate(View container) {
        // TODO Auto-generated method stub
        Log.d(TAG, "startUpdate()");
    }




    public class TtsButton extends Activity implements OnInitListener {

        public TtsButton(OnClickListener onClickListener, String inputTxt) {
            super();
            tTSCheck(inputTxt);
        }

        private void tTSCheck (String inputTxt) {

            int resultCodeCheck = TextToSpeech.Engine.CHECK_VOICE_DATA_PASS;
            if (resultCodeCheck == 1) {
                btnTTS = new TextToSpeech(context, this);
            } else {
                Intent installTTSFiles = new Intent(); //missing data, install it
                installTTSFiles.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTTSFiles);
            }
        }

        @Override
        public void onInit(int status) {
            // TODO Auto-generated method stub
            if(status == TextToSpeech.SUCCESS)
            {
                Log.i(TAG, "TTS INIT: SUCCESS");
                btnTTS.setLanguage(Locale.US);
                btnTTS.speak(inputTxt, TextToSpeech.QUEUE_FLUSH, null);
            }
            else if(status == TextToSpeech.ERROR)
            {
                Log.e(TAG, "TTS INIT: ERROR");
            }
        }

        @Override
        public void onPause() {
            if (btnTTS != null) {
                btnTTS.stop();
                btnTTS.shutdown();
            }
            super.onPause();
        }

    } //end embedded class

} //end ViewPagerAdapter

提前致谢。我正在考虑尝试使用动作手势,但是,我真的不明白为什么我的方法不会工作这么久,以至于我可以在正确的位置调用它。我最初的想法是每次位置发生变化并且条件正确时在“Object instantiateItem(ViewGroup container, final int position)”中调用它。但我不确定这是否最好。

【问题讨论】:

标签: android scroll android-viewpager


【解决方案1】:

这是一个没有虚假页面的解决方案,效果很好:

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

您只需将其设置为您的 ViewPager 为 onPageChangeListener 即可:

viewPager.setOnPageChangeListener(new CircularViewPagerHandler(viewPager));

为避免在 ViewPager 的“末尾”出现这种蓝色光芒,您应该将此行应用于放置 ViewPager 的 xml:

android:overScrollMode="never"

【讨论】:

  • 如果从 laspage 到第 1 年龄从右向左滑动,则无法保持滑动动画,第 1 页出现时没有任何动画,反之亦然,此外,如果您启用平滑滚动,则在他的代码中它会跳转在无限循环中来回到第一页和最后一页--> mViewPager.setCurrentItem(0, true);
  • 我已经改进了上面的解决方案,并在 github 上创建了一个小库。随时查看:) github.com/TobiasBuchholz/CircularViewPager
  • 嗨!我试过你的答案,结果你是否会在mViewPager.setCurrentItem(0, true); 启用 平滑滚动 然后它会继续来回滚动。
  • 嗨,我已经通过以下检查修复了平滑滚动:if (state == ViewPager.SCROLL_STATE_IDLE && mScrollState == ViewPager.SCROLL_STATE_DRAGGING)
  • 谢谢,但是滚动不流畅,上面的提示没有帮助。
【解决方案2】:

好的,我有一个答案。这实际上比我预期的要容易,但确实需要一些技巧。首先,让我从设置开始。例如,假设您在 ViewPager 中滚动浏览三个页面 (A-B-C)。并且您想要设置它,以便如果您继续在 C 上滚动(第 3 页),它会转到 A(第 1 页),如果您在 A(第 1 页)上向后滚动,它会转到 C(第 3 页) )。

我并不是说我的解决方案是最好的,但它确实有效,而且我没有发现任何问题。首先,您必须创建两个“假”页面。虚假页面代表 ViewPager 的第一页和最后一页。接下来需要设置一个 onPageChangeListener(),并使用 onPageSelected() 方法。您需要假页面的原因是 onPageSelected() 仅在您移动(滑动)后注册。换句话说,如果没有这种方法,最终用户将不得不滚动到第 2 页并返回到第 1 页才能在第 1 页上收到点击,这也意味着根据您的代码逻辑将跳过第 1 页。

设置确实是完整的答案。有了假页面后,只需在必要的方法中使用 setCurrentItem() 即可。

这是我的代码的外观。请务必将其放在您的公共 Object instantiateItem(final ViewGroup container, final int position) 方法中,就在您将视图返回到容器中之前。

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

                // skip fake page (first), go to last page
                if (position == 0) {
                    ((ViewPager) container).setCurrentItem(118, false);
                }

                // skip fake page (last), go to first page
                if (position == 119) {
                    ((ViewPager) container).setCurrentItem(1, false); //notice how this jumps to position 1, and not position 0. Position 0 is the fake page!
                }

            }

就是这样,它成功了!唯一要做的另一件事是在位置 1 上启动 ViewPager(这是第二页:假页面 = pg 1,我的真实起始页面 = pg 2)。现在,每次我滚动到虚假页面时,我都会将其重定向到最后一个真实页面。每次我向前滚动到最后一个假页面时,我都会将其重定向到真正的起始页面(第 2 页)。

另外,不要尝试在 onPageScrollStateChanged 中放入任何代码。那个方法很诡异,好像状态值不可控。它不断地从一种状态跳到另一种状态。即使没有滚动。这只是我收到的一个提示。

【讨论】:

  • 完美,但如何让滚动流畅?
  • setCurrentItem(1, true) 平滑滚动
  • 不错的解决方案!问题是我首先看到的虚假页面非常简短,然后我立即看到了正确的页面。我使用安卓X。如何解决?
【解决方案3】:

我创建了圆形查看器,在向左滑动时从最后一个到第一个平滑滚动,在向右滑动时从第一个到最后一个平滑滚动。

为此,将最后一页添加到起始页,将第一页添加到最后一页: 在 addOnPageChangeListener 内部:我们必须进行一些计算,当我们处于 0 位置时,onPageScrollStateChanged 将当前项设置为最后一项,反之亦然。

查看代码

public class ViewPagerCircular_new extends AppCompatActivity {
ViewPager viewPager;
ArrayList<String> str = new ArrayList<String>();
boolean chageImage = false;
int setPos;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view_pager_normal);
    viewPager = (ViewPager) findViewById(R.id.vf_home_top_pager);
    str.add("6");         // added the last page to the frist
    str.add("1");        // First item to display in view pager
    str.add("2");
    str.add("3");
    str.add("4");
    str.add("5");
    str.add("6");     // last item to display in view pager
    str.add("1");      // added the first page to the last
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
    {

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
        {
            if (position == str.size() - 1)
            {
                chageImage = true;
                setPos = 1;
            } else if (position == 0)
            {
                chageImage = true;
                setPos = str.size() - 2;
            } else
            {
                chageImage = false;
            }
        }

        @Override
        public void onPageSelected(int position)
        {
        }

        @Override
        public void onPageScrollStateChanged(int state)
        {
            if (state == ViewPager.SCROLL_STATE_IDLE && chageImage)
            {
                viewPager.setCurrentItem(setPos, false);
            }
        }
    });
// display the 1st item as current item 
    viewPager.setCurrentItem(1);
}

// 寻呼机适配器

public class ViewPagerAdapter extends FragmentStatePagerAdapter
{

    public ViewPagerAdapter(FragmentManager fm)
    {
        super(fm);
    }

    @Override
    public Fragment getItem(int position)
    {
        PagerFragment fragment = new PagerFragment();
        Bundle bundle = new Bundle();
        bundle.putString("pos", str.get(position));
        fragment.setArguments(bundle);
        return fragment;
    }

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

}

// 在适配器中显示的片段

public class PagerFragment extends Fragment
{

    Bundle bundle;
    String pos;

    public PagerFragment()
    {
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        bundle = getArguments();
        pos = bundle.getString("pos");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        TextView textView = new TextView(ViewPagerCircular_new.this);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(25);
        textView.setText(pos);
        return textView;
    }

}

}

【讨论】:

    【解决方案4】:

    试试这个

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

    【讨论】:

    • 完美运行。由于我使用的是 CirclePageIndicator,因此我无法在开头和结尾添加假页面。使用此代码,我可以轻松地传播我的 ViewPager。
    • @RohanKandwal 你可以在这里粘贴你的工作代码吗?因为在我的情况下,解决方案不起作用。
    • 闪烁看起来很糟糕!
    【解决方案5】:

    我稍微修改了@portfoliobuilder 的答案。这很简单。 将直到PageChangeState 之前没有平滑滚动的当前项设置为“0”,这样会非常平滑。

    ((ViewPager)container).setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        }
    
        @Override
        public void onPageSelected(int position) {
            currentPage = position;
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
    
            // state equals to 0 means the scroll action is stop
            if(state == 0) {
    
                if(currentPage == 0)
                    ((ViewPager)container).setCurrentItem(imageResourceList.size()-2,false);
    
                if(currentPage == imageResourceList.size()-1)
                    ((ViewPager)container).setCurrentItem(1,false);
            }
        }
    });
    

    【讨论】:

      【解决方案6】:

      这是我的解决方案:

      myviewpager.java

      public class myViewPager extends PagerAdapter {
      
          public myViewPager (Context context) {
              this.context = context;
          }
      
          @Override
          public int getCount() {
              return rank.length+2;
          }
      
          @Override
          public boolean isViewFromObject(View view, Object object) {
              return view == object;
          }
      
          @Override
          public Object instantiateItem(ViewGroup container, int position) {
              // Declare Variables
      
              TextView textViewRank;
      
      
      
              //Log.i(TAG, "get position = "+position);
      
              inflater = (LayoutInflater) context
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
              View itemView = inflater.inflate(R.layout.viewpager_item, container,
                  false);
      
              textViewRank= (TextView) itemView.findViewById(R.id.textView1);
      
              if (position == getCount() - 1) {
                  textViewRank.setText(rank[0]);
              } else if (position == 0) {
                  textViewRank.setText(rank[rank.length-1]);
              } else {
                  textViewRank.setText(rank[position-1]);
              }
      
      
              ((ViewPager) container).addView(itemView);
      
              return itemView;
          }
          @Override
          public void destroyItem(ViewGroup container, int position, Object object) {
              container.removeView((View) object);
          }
      }
      

      ViewPager_Item.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:orientation="horizontal" android:layout_width="match_parent"
          android:layout_height="match_parent">
      
          <TextView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:layout_weight="1"
                  android:id="@+id/textView1"/>
      </LinearLayout>
      

      mainActivity.java

      public class MainActivity extends AppCompatActivity {
          private static final String TAG = MainActivity.class.getName();
          public static String[] rank;
          myViewPager adapter;
          private ViewPager viewPager;
          private static int currentPage;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              rank = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
              viewPager = (ViewPager) findViewById(R.id.view_pager);
              adapter = new myViewPager(this);
      
              viewPager.setAdapter(adapter);
      
              viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                  @Override
                  public void onPageSelected(int position) {
                      Log.i(TAG, "onPageSelected = "+position);
                      currentPage = position;
                  }
                  @Override
                  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                      // not needed
                  }
                  @Override
                  public void onPageScrollStateChanged(int state) {
                      if (state == ViewPager.SCROLL_STATE_IDLE) {
                          int pageCount = rank.length+2;
      
                          if (currentPage == pageCount-1){
                              viewPager.setCurrentItem(1,false);
                          } else if (currentPage == 0){
                              viewPager.setCurrentItem(pageCount-2,false);
                          }
                      }
                  }
              });
          }
      
      
      }
      

      activity_main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical" android:layout_width="match_parent"
          android:layout_height="match_parent">
      
          <android.support.v4.view.ViewPager
              android:id="@+id/view_pager"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_weight="1" />
      
      </LinearLayout>
      

      假设阵列有10个元素。然后“添加”2个虚拟元素,但并非真正添加。当调用“get_count”函数时,只需返回大小= 10 + 2元素。

      [p> k0] e [1] e [2] e [3] e [4] e [5] e [5] e [6] e [6] e [7] e [8] e [9] e [9]虚拟

      在ViewPager.AddonpageChangelistener:

      当您幻灯片到最后一个元素时,ViewPager应将第一个元素设置为下一个元素。

      if (currentPage == pageCount-1){
          viewPager.setCurrentItem(1,false);
      }
      

      当您滑动到第一个元素时,ViewPager应将最后一个元素设置为下一个元素。

      else if (currentPage == 0){
          viewPager.setCurrentItem(pageCount-2,false);
      }
      

      在InstantialeItem:

       if (position == getCount() - 1) {
          textViewRank.setText(rank[0]);
       } else if (position == 0) {
          textViewRank.setText(rank[rank.length-1]);    
       } else {
          textViewRank.setText(rank[position-1]);
       }
      

      【讨论】:

        【解决方案7】:

        它是一个简单的例子,监听器的重要部分是在 STATE_IDLE 检测循环结束点。 所以首先实现 OnPageChangeListener 类,然后在你的处理程序类上添加这部分:

        @Override
            public void onPageScrollStateChanged(int state) {
        
                if (state == ViewPager.SCROLL_STATE_IDLE) {
        
                    if (mPreviousPosition == mCurrentPosition && !mIsEndOfCycle) {
        
                        if (mCurrentPosition == 0) {
                            mViewPager.setCurrentItem(getAdapterItemsCount() - 1);
                        } else {
                            mViewPager.setCurrentItem(0);
                        }
        
                        mIsEndOfCycle = true;
                    } else {
                        mIsEndOfCycle = false;
                    }
        
                    mPreviousPosition = mCurrentPosition;
                }
        
            }
        

        【讨论】:

          【解决方案8】:

          我尝试了@portfoliobuilder 的解决方案,非常棒。但是有个小问题:当当前item是head或者tail时,如果我只是点击ViewPager,不拖拽,item会变成tail或者head。我在 ViewPager 中添加了一个触摸监听器来解决这个问题。

          skinPager.setOnTouchListener(new OnTouchListener() {
          
                  @Override
                  public boolean onTouch(View v, MotionEvent event) {
                      //Record the x when press down and touch up, 
                      //to judge whether to scroll between head and tail
                      int x = (int) event.getX();
                      int y = (int) event.getY();
                      if(event.getAction() == MotionEvent.ACTION_DOWN)
                          skinPagerPressX = x;
                      else if(event.getAction() == MotionEvent.ACTION_UP)
                          skinPagerUpX = x;
                      return false;
                  }
              });
          

          以下是portfoliobuilder的修改功能:

          private void handleSetNextItem() {
              final int lastPosition = skinPager.getAdapter().getCount() - 1;
              //Only scroll when dragged
              if(mCurrentPosition == 0 && skinPagerUpX > skinPagerPressX) {
                  skinPager.setCurrentItem(lastPosition, false);
              } else if(mCurrentPosition == lastPosition && skinPagerUpX < skinPagerPressX) {
                  skinPager.setCurrentItem(0, false);
              }
          }
          

          【讨论】:

            【解决方案9】:

            @tobi_b 的答案并不完全成功,因为它不能顺利地从最后一个滑到第一个(至少在我的试验中)。但我真的被他的回答鼓舞了。 我的解决方案是何时从假的最后一个跳到真正的第一个,等到最后一个滚动完成。这是我的代码,很简单,

            private final class MyPageChangeListener implements OnPageChangeListener {
            
                private int currentPosition;
            
                @Override
                public void onPageScrollStateChanged(int state) {
                    if (state == ViewPager.SCROLL_STATE_IDLE) {
                        if (currentPosition == viewPager.getAdapter().getCount() - 1) {
                            viewPager.setCurrentItem(1, false);
                        }
                        else if (currentPosition == 0) {
                            viewPager.setCurrentItem(viewPager.getAdapter().getCount() - 2, false);
                        }
                    }
                }
            
                @Override
                public void onPageScrolled(int scrolledPosition, float percent, int pixels) {
                    //empty
                }
            
                @Override
                public void onPageSelected(int position) {
                    currentPosition = position;
                }
            
            }
            

            但是,这个解决方案并不完美。从最后一个快速滑到第一个时,它有一个小缺陷。如果我们在很短的时间内滑动两次,第二次滑动就会失效。这个问题需要解决。

            【讨论】:

              【解决方案10】:

              解决首页到最后一页从右到左滑动时动画缺失问题

              对@tobi_b 的回答稍作修改,解决了我的问题。 为此,将起始页的最后一页和第一页的副本添加到最后一页。然后只需从 PagerAdapter 中的以下方法中删除 NOT 运算符。并将 setCurrentItem(lastposition,false) 更改为 setCurrentItem(lastposition-1,false) 和setCurrentItem(0,false) 到 setCurrentItem(1,false)。

              private void setNextItemIfNeeded() {
                  if (isScrollStateSettling()) {
                      handleSetNextItem();
                  }
              }
              
              private boolean isScrollStateSettling() {
                  return mScrollState == ViewPager.SCROLL_STATE_SETTLING;
              }
              private void handleSetNextItem() {
                  final int lastPosition = pager.getAdapter().getCount() - 1;
                  if(mCurrentPosition == 0) {
                      pager.setCurrentItem(lastPosition-1, false);
                  } else if(mCurrentPosition == lastPosition) {
                     pager.setCurrentItem(1, false);
                  }
              }
              

              并且在您的 MainActivity.java 中不要忘记将当前项目设置为 1。 希望这会有所帮助。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-10-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多