无限滚动图像ViewPager
正如Google所logging的那样,Gallery类在API级别16中已被弃用。不再支持此小部件。 其他水平滚动的小部件包括支持库中的HorizontalScrollView和ViewPager。 所以我用ViewPager作为Gallery类的替代品。
我的目标是最终实现带有文本描述的无限滚动图像ViewPager 。 我用下面的代码来实现图像ViewPager与描述每个图像的文本,但我如何将无限滚动应用到ViewPager?
我之前没有使用过ViewPager,请尽可能提供详细的代码。
activity_main.xml中:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/myimagepager" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
custom_pager.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal"> <ImageView android:id="@+id/myimage" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="5dp" android:layout_weight="2" /> <TextView android:id="@+id/image_text" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout>
ImagePager:
public class ImagePager extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImagePagerAdapter adapter = new ImagePagerAdapter(this, imageArra, stringArray ); ViewPager myPager = (ViewPager) findViewById(R.id.myimagepager); myPager.setAdapter(adapter); myPager.setCurrentItem(0); } private int imageArra[] = { R.drawable.a, R.drawable.b,R.drawable.c, R.drawable.d,R.drawable.e,R.drawable.f, R.drawable.g, R.drawable.h, R.drawable.i}; private String[] stringArray = new String[] { "Image a", "Image b","Image c" "Image d","Image e","Image f", "Image g","Image h","Image i"}; }
ImagePagerAdapter:
public class ImagePagerAdapter extends PagerAdapter { Activity activity; int imageArray[]; String[] stringArray; public ImagePagerAdapter(Activity act, int[] imgArra, String[] stringArra) { imageArray = imgArra; activity = act; stringArray = stringArra; } public int getCount() { return imageArray.length; } public Object instantiateItem(View collection, int position) { LayoutInflater inflater = (LayoutInflater)collection.getContext ().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View layout = inflater.inflate(R.layout.custom_pager, null); ImageView im=(ImageView) layout.findViewById(R.id.myimage); im.setImageResource(imageArray[position]); TextView txt=(TextView) layout.findViewById(R.id.image_text); txt.setText(stringArray[position]); ((ViewPager) collection).addView(layout, 0); return layout; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView((View) arg2); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == ((View) arg1); } @Override public Parcelable saveState() { return null; } }
我有同样的问题 ,但我能find一种方法来解决它的代码可以在github上find。
如果您将类InfiniteViewPager和InfinitePagerAdapter复制到您的项目中,您可以通过一些小的更改来实现无限(包装)滚动。
在你的活动中,用一个InfinitePagerAdapter
包装你的PagerAdapter:
PagerAdapter adapter = new InfinitePagerAdapter(new ImagePagerAdapter(this, imageArra, stringArray));
将活动XML中的ViewPager更改为InfiniteViewPager
:
<com.antonyt.infiniteviewpager.InfiniteViewPager android:id="@+id/myimagepager" android:layout_width="match_parent" android:layout_height="match_parent" />
您可以将类重命名为任何你想要的。 如果您至less有三个页面(您的示例代码中有九个,那么这个代码就可以正常工作)。
我已经find了一个简单的方法,我希望它对你有帮助
import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.Log; public class ImagePager extends Activity { String[] stringArray; int[] imageArra; ViewPager myPager; Boolean isScrooled = false; // use this array yo understand swipe left or right ? ArrayList<Float> pos = new ArrayList<Float>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // put empty view at the beginnig and to end imageArra = new int[] { 0, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, 0 }; // put empty string at the beginnig and to end stringArray = new String[] { "", "Image a", "Image b", "Image c", "Image d", "Image e", "Image f", "Image g", "Image h", "Image i", "" }; ImagePagerAdapter adapter = new ImagePagerAdapter(this, imageArra, stringArray); myPager = (ViewPager) findViewById(R.id.myimagepager); myPager.setAdapter(adapter); myPager.setCurrentItem(1); myPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { Log.v("onPageSelected", String.valueOf(arg0)); pos.clear(); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { try { // while scrolling i add ever pos to array pos.add(arg1); // if pos.get(0) > pos.get(pos.size() - 1) // <----- swipe <----- // we should check isScroll because setCurrent item is not a croll ? if (pos.size() > 0) if (arg0 == imageArra.length - 1 & pos.get(0) > pos.get(pos.size() - 1) & isScrooled == true) { try { isScrooled = false; myPager.setCurrentItem(1, false); } catch (Exception e) { Log.v("hata", "<----- swipe <----- " + e.toString()); } } // ----> swipe ----> else if (arg0 == 0 & pos.get(0) < pos.get(pos.size() - 1) & isScrooled == true) { try { isScrooled = false; myPager.setCurrentItem(imageArra.length - 1, false); } catch (Exception e) { Log.v("hata", "----> swipe ----> " + e.toString()); } } else if (arg0 == 0 & pos.size() == 1 & isScrooled == true) { try { isScrooled = false; myPager.setCurrentItem(imageArra.length - 1, false); } catch (Exception e) { Log.v("hata", "----> swipe ----> " + e.toString()); } } } catch (Exception e) { Log.v("hata", e.toString()); } } @Override public void onPageScrollStateChanged(int arg0) { Log.v("onPageScrollStateChanged", String.valueOf(arg0)); // set is scrolling isScrooled = true; } }); } }
[编辑1]
import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.Log; public class ImagePager extends Activity { String[] stringArray; int[] imageArra; ViewPager myPager; int scrollState; Boolean isFirstVisitEnd= true,isFirstVisitBegin = true; ArrayList<Integer> pos = new ArrayList<Integer>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageArra = new int[] { 0,R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, R.drawable.ic_launcher, 0 }; stringArray = new String[] {"","Image a", "Image b", "Image c", "Image d", "Image e", "Image f", "Image g", "Image h", "Image i", "" }; ImagePagerAdapter adapter = new ImagePagerAdapter(this, imageArra, stringArray); myPager = (ViewPager) findViewById(R.id.myimagepager); myPager.setAdapter(adapter); myPager.setCurrentItem(1); myPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { Log.v("onPageSelected", String.valueOf(arg0)); pos.clear(); if (arg0 == imageArra.length - 1) isFirstVisitEnd = false; else isFirstVisitEnd = true; if (arg0 == 0) isFirstVisitBegin = false; else isFirstVisitBegin = true; } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { try { pos.add(Integer.valueOf(arg2)); if (pos.size() > 0) { //Log.v("onPageScrolled_arg2","arg0 : "+String.valueOf(arg0)+" ilk : "+pos.get(0).toString()+" son : " +pos.get(pos.size() - 1).toString()+ " "+ String.valueOf(pos.get(0)-(pos.get(pos.size() - 1)))+" isFirstVisitEnd: "+String.valueOf(isFirstVisitEnd.booleanValue()) ); // <----- swipe <----- if (arg0 == imageArra.length - 2& (pos.get(pos.size() - 1) -pos.get(0) < 100)& scrollState == 2 & isFirstVisitEnd == false) { myPager.setCurrentItem(1, false); } //Log.v("onPageScrolled_arg2","arg0 : "+String.valueOf(arg0)+" ilk : "+pos.get(0).toString()+" son : " +pos.get(pos.size() - 1).toString()+ " "+ String.valueOf(pos.get(0)-(pos.get(pos.size() - 1)))+" isFirstVisitbegin: "+String.valueOf(isFirstVisitBegin.booleanValue()) ); if (arg0 == 0 & (pos.get(pos.size() - 1) -pos.get(0) > -100)& scrollState == 2 & isFirstVisitBegin == false) { myPager.setCurrentItem(imageArra.length - 2, false); } } } catch (Exception e) { Log.v("hata", e.toString()); } } @Override public void onPageScrollStateChanged(int arg0) { Log.v("onPageScrollStateChanged", String.valueOf(arg0)); scrollState =arg0; } }); } }
我认为我的解决scheme更简单。
注意我的图像arrays结构:
Item 0 => last image Item count()-1 => first image
技巧是onPageScrollStateChanged
:
当用户滚动到最后一个项目 – >分页跳转没有animation到第一个图像(位置= 1)
当用户滚动到第一个项目 – >传呼机没有animation跳转到最后一个图像(position = count – 2)
public class InfiniteScrollingActivity extends ActionBarActivity { private ViewPager pager; private MyAdapter adapter; int[] promoImageIds = new int[]{R.drawable.cover6, R.drawable.cover1, R.drawable.cover2, R.drawable.cover3, R.drawable.cover4, R.drawable.cover5, R.drawable.cover6, R.drawable.cover1 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my_test); adapter = new MyAdapter(getSupportFragmentManager(), promoImageIds); pager = (ViewPager)findViewById(R.id.pager); pager.setAdapter(adapter); pager.setCurrentItem( 1 ); pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int index) { Log.v( "onPageSelected", String.valueOf( index ) ); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // Log.v("onPageScrolled", ""); } @Override public void onPageScrollStateChanged(int state) { Log.v("onPageScrollStateChanged", String.valueOf(state)); if (state ==ViewPager.SCROLL_STATE_IDLE) { int index = pager.getCurrentItem(); if ( index == 0 ) pager.setCurrentItem( adapter.getCount() - 2, false ); else if ( index == adapter.getCount() - 1 ) pager.setCurrentItem( 1 , false); } } }); } public static class MyAdapter extends FragmentPagerAdapter { int[] promoImageIds; public MyAdapter(FragmentManager fm, int[] promoImageIds){ super(fm); this.promoImageIds = promoImageIds; } @Override public int getCount(){ return promoImageIds.length; } @Override public Fragment getItem(int position) { return PromoFragment.newInstance( promoImageIds[position] ); } } public static class PromoFragment extends Fragment { int imageID; static PromoFragment newInstance( int imageID) { PromoFragment f = new PromoFragment(); // Supply num input as an argument. Bundle args = new Bundle(); args.putInt( "imageID", imageID ); f.setArguments(args); return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); imageID = getArguments() != null ? getArguments().getInt( "imageID" ) : null; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ImageView v = (ImageView) inflater.inflate(R.layout.fragment_image, container, false); v.setImageResource( imageID ); return v; } } }
对于天数无限的滚动,重要的是你在寻呼机中有好的片段,因此我在页面上写了我的答案( Android中的Viewpager在无休止的几天之间切换 )
它工作得很好! 以上的答案不适合我,因为我想要它的工作。
RecyclerViewPager已经实现infinite scrolling
并可以滚动像一个画廊。
我发现另一个解决scheme,基于希洛米哈森和antonyt的答案,没有修改收集。
ViewPager yourPager; PagerAdapter yourAdapter; //.... EndlessPagerAdapter endlessPagerAdapter = new EndlessPagerAdapter(yourAdapter, yourPager); yourPager.setAdapter(endlessPagerAdapter); yourPager.setCurrentItem(1);//for correct first page
全class:
public class EndlessPagerAdapter extends PagerAdapter { private PagerAdapter adapter; public EndlessPagerAdapter(PagerAdapter adapter, ViewPager viewPager) { this.adapter = adapter; viewPager.addOnPageChangeListener(new SwapPageListener(viewPager)); } @Override public int getCount() { return adapter.getCount() + 2; } @Override public Object instantiateItem(ViewGroup container, int position) { if (adapter.getCount() < 2) { adapter.instantiateItem(container, position); } int newPosition; if (position == 0) { newPosition = adapter.getCount() - 1; } else if (position >= getCount() - 1) { newPosition = 0; } else { newPosition = position - 1; } return adapter.instantiateItem(container, newPosition); } @Override public void destroyItem(ViewGroup container, int position, Object object) { adapter.destroyItem(container, position, object); } @Override public void finishUpdate(ViewGroup container) { adapter.finishUpdate(container); } @Override public boolean isViewFromObject(View view, Object object) { return adapter.isViewFromObject(view, object); } @Override public void restoreState(Parcelable bundle, ClassLoader classLoader) { adapter.restoreState(bundle, classLoader); } @Override public Parcelable saveState() { return adapter.saveState(); } @Override public void startUpdate(ViewGroup container) { adapter.startUpdate(container); } @Override public CharSequence getPageTitle(int position) { return adapter.getPageTitle(position); } @Override public float getPageWidth(int position) { return adapter.getPageWidth(position); } @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { adapter.setPrimaryItem(container, position, object); } @Override public void unregisterDataSetObserver(DataSetObserver observer) { adapter.unregisterDataSetObserver(observer); } @Override public void registerDataSetObserver(DataSetObserver observer) { adapter.registerDataSetObserver(observer); } @Override public void notifyDataSetChanged() { adapter.notifyDataSetChanged(); } @Override public int getItemPosition(Object object) { return adapter.getItemPosition(object); } private class SwapPageListener implements ViewPager.OnPageChangeListener { private ViewPager viewPager; SwapPageListener(ViewPager viewPager) { this.viewPager = viewPager; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { PagerAdapter pagerAdapter = viewPager.getAdapter(); if (pagerAdapter != null) { int itemCount = pagerAdapter.getCount(); if (itemCount < 2) { return; } int index = viewPager.getCurrentItem(); if (index == 0 ) { viewPager.setCurrentItem(itemCount - 2, false); } else if (index == itemCount - 1) { viewPager.setCurrentItem(1, false); } } } } }}
怎么运行的:
我们有一些收集
然后添加两个额外的项目
在最后位置显示第一个元素,在第一个位置显示最后一个元
添加事件监听器和交换页面,从4到1,从0到3
就这样。
我不会build议你在那里应用animation或者布局繁琐,当元素交换的时候可能会比较滞后(也许我没有遇到任何延迟)
也不要将此适配器多次设置为分页器,或者将SwapPageListener移动到外部类,并将其设置在初始化块中。