2012年10月29日月曜日

How to create looping ViewPager

ループできる ViewPager です。ちゃんと作ってないので以下の制限があります。
  • ページ数が 3の倍数じゃないといけない(時間がなくて対応してない)
  • 連続ページ切り替え(スワイプ後のスクロールが終わる前にさらにスワイプ)に対応してない
  • わかんないけどなんかあるかも
ポイントは isViewFromObject() を駆使することと、ViewPager を extends して onLayout で位置を戻すことです。 public class MainActivity extends Activity { private ViewPager mViewPager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mPagerAdapter = new MyPagerAdapter(this); mViewPager = (ViewPager) findViewById(R.id.viewpager); mViewPager.setOffscreenPageLimit(2); mViewPager.setAdapter(mPagerAdapter); mViewPager.setOnPageChangeListener(mPagerAdapter); mViewPager.setCurrentItem(1, false); } private MyPagerAdapter mPagerAdapter; private class MyPagerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener { /** * from 0 to 2 */ int focusedPosition = 0; /** * from 0 to PAGE_NUM -1 */ int contentPosition = 0; /** * number of pages (3x) */ int PAGE_NUM = 9; Context mContext; LayoutInflater mInflater; public MyPagerAdapter(Context context) { mContext = context; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return 3; } SparseArray<View> mViews = new SparseArray<View>(); @Override public Object instantiateItem(ViewGroup container, int position) { int newPosition = calcContentPosition(position); View view = createContent(newPosition); container.addView(view, 0); mViews.put(position, view); view.setTag(position); // return view; return Integer.valueOf(position); } @Override public boolean isViewFromObject(View view, Object object) { int index = (Integer) view.getTag(); int position = (Integer) object; int newPosition = (position + contentPosition) % 3; return newPosition == index; } /** * create content's view * * @param position * from 0 to PAGE_NUM - 1 * @return */ private View createContent(int position) { View view = mInflater.inflate(R.layout.list, null, false); updateContent(view, position); return view; } /** * update content's view * * @param view * @param position * from 0 to PAGE_NUM -1 */ private void updateContent(View view, int position) { ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, android.R.layout.simple_list_item_1, createList(position)); ListView listView = (ListView) view.findViewById(R.id.list); listView.setAdapter(adapter); listView.setScrollingCacheEnabled(false); } private List<String> createList(int index) { List<String> list = new ArrayList<String>(); for (int i = 0; i < 50; i++) { list.add(index + " *************************** " + index + ":" + (i + 1)); } return list; } /** * get position of content * * @param position * from 0 to 2 * @return content position (from 0 to PAGE_NUM - 1) */ private int calcContentPosition(int position) { int offset = position - 1; int newPosition = contentPosition + offset; if (newPosition < 0) { newPosition = PAGE_NUM - 1; } else { newPosition = newPosition % PAGE_NUM; } return newPosition; } @Override public void destroyItem(ViewGroup container, int position, Object object) { int count = mViewPager.getChildCount(); int index = (Integer) object; for (int i = 0; i < count; i++) { View v = mViewPager.getChildAt(i); if (isViewFromObject(v, Integer.valueOf(index))) { container.removeView(v); break; } } } /** * update specified view's content * * @param index * 0 or 2 */ void updateContents(int index) { int count = mViewPager.getChildCount(); for (int i = 0; i < count; i++) { View v = mViewPager.getChildAt(i); if (isViewFromObject(v, Integer.valueOf(index))) { final int newPosition = calcContentPosition(index); updateContent(v, newPosition); break; } } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { focusedPosition = position; } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { handlePageScrollStateChangedToIdle(); } } private void handlePageScrollStateChangedToIdle() { switch (focusedPosition) { case 0: // scroll to previous page if ((--contentPosition) < 0) { contentPosition = PAGE_NUM - 1; } updateContents(0); break; case 2: // scroll to next page contentPosition = (++contentPosition) % PAGE_NUM; updateContents(2); break; default: break; } } } } public class MyViewPager extends ViewPager { public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(getCurrentItem() != 1) { setCurrentItem(1, false); } } } res/layout/main.xml <?xml version="1.0" encoding="utf-8"?> <com.sample.viewpager.MyViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" /> res/layout/list.xml <?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" />

3 件のコメント:

  1. It doesn't work when I put a methode
    @Override
    public float getPageWidth(int position) {
    return 0.4f;
    }
    in MyPagerAdapter class

    返信削除
  2. And also how can i change it all for fragment instead of Views

    返信削除