Can ViewPager have multiple views in per page?
在尝试了"画廊"和"水平滚动视图"之后,我发现"视图寻呼机"可以满足我的需求,但缺少一小部分内容。 查看寻呼机每页可以有多个视图吗?
我知道View Pager每次滑动仅显示1个视图/页面。 我想知道是否可以限制视图宽度,以便显示下面的第二个视图?
例如:我有3个视图,并且我希望屏幕显示视图1和视图2的一部分,以便用户知道还有更多内容,因此他们可以滑动视图2。
1 2 | |view 1|view 2|view 3| |screen | |
通过为ViewPager指定负边距,我发现了一个甚至更简单的解决方案。我已经在GitHub上创建了MultiViewPager项目,您可能需要看一下:
https://github.com/Pixplicity/MultiViewPager
尽管MultiViewPager期望使用子视图来指定尺寸,但是原理围绕着设置页边距进行:
1 2 | ViewPager.setPageMargin( getResources().getDimensionPixelOffset(R.dimen.viewpager_margin)); |
然后,在
1 | <dimen name="viewpager_margin">-64dp</dimen> |
为了补偿重叠的页面,每个页面的内容视图都有相反的边距:
1 2 | android:layout_marginLeft="@dimen/viewpager_margin_fix" android:layout_marginRight="@dimen/viewpager_margin_fix" |
再次在
1 | <dimen name="viewpager_margin_fix">32dp</dimen> |
(请注意,
我们在荷兰报纸应用程序De Telegraaf Krant中实现了这一点:
马克·墨菲(Mark Murphy)有一篇有趣的博客文章专门针对此问题。尽管我最终在该线程中使用了自己的解决方案,但值得一看的是Dave Smith的代码,Mark在博客文章中引用了该代码:
https://gist.github.com/8cbe094bb7a783e37ad1/
警告!在采用这种方法之前,请注意这种方法的一些非常严重的问题,这些问题在本文结尾处和下面的评论中均提到。
您将得到以下结果:
通过将
在XML中,这非常简单:
1 2 3 4 5 6 7 8 9 10 | <com.example.pagercontainer.PagerContainer android:id="@+id/pager_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#CCC"> <android.support.v4.view.ViewPager android:layout_width="150dp" android:layout_height="100dp" android:layout_gravity="center_horizontal" /> </com.example.pagercontainer.PagerContainer> |
添加一些代码来处理
话虽这么说,虽然总体上可以正常工作,但我确实注意到,存在一个边缘情况,用这种相当简单的结构无法解决:在
可以在同一屏幕上显示多个页面。
一种方法是通过重写PAgerAdapter中的getPageWidth()方法。 getPageWidth()返回一个介于0和1之间的浮点数,指示该页面应占据Viewpager多少宽度。默认情况下,它设置为1。因此,您可以将其更改为所需的宽度。
您可以在此处和github项目中阅读有关此内容的更多信息。
这是我的方法:
1 2 3 4 5 6 7 8 9 10 | <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center" android:layout_marginBottom="8dp" android:clipToPadding="false" android:gravity="center" android:paddingLeft="36dp" android:paddingRight="36dp"/> |
在活动中,我使用这个:
1 | markPager.setPageMargin(64); |
希望能帮助到你!
我有一个相同的问题,唯一的区别是我需要一次显示3页(上一页,当前页和下一页)。经过对最佳解决方案的长期研究,我认为我找到了它。
解决方案是这里的一些答案的混合:
正如@Paul Lammertsma的回答所指出的那样-Mark Murphy博客中Dave Smith的代码是解决方案的基础。对我来说,唯一的问题是
1 2 | android:layout_width="150dp" android:layout_height="100dp" |
这对我的目的不利,因为我一直在寻找会散布在整个屏幕上的东西。所以我将其更改为包装内容,如您在此处看到的:
1 2 3 4 5 6 7 8 9 10 | <com.example.nutrino_assignment.PagerContainer android:id="@+id/pager_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#CCC"> <android.support.v4.view.ViewPager android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </com.example.nutrino_assignment.PagerContainer> |
现在,我失去了本教程尝试执??行的所有操作。使用@andro的答案,我一次可以显示多于1页:正好2张!当前和下一个。
通过覆盖如下内容来做到这一点:
1 2 3 4 | @Override public float getPageWidth(int position) { return(0.9f); } |
那几乎是我所需要的...(即使我认为足以满足您的要求),但对于其他可能需要我所需要的东西的人:
对于解决方案的最后一部分,我还是在@Paul Lammertsma的回答中使用了这个想法。
在Dave Smith的代码中,您会在
1 2 | //A little space between pages pager.setPageMargin(15); |
我替换为:
1 2 | //A little space between pages pager.setPageMargin(-64); |
现在在第一页上看起来:
1 2 | |view 1|view 2|view 3| |screen | |
而在第二个看起来像:
1 2 | |view 1|view 2|view 3| |screen | |
希望它能对某人有所帮助!我浪费了大约2天的时间...
祝好运。
1 | viewPager.setPageMargin(-18);// adjust accordingly ,-means less gap |
在图像适配器中
1 2 3 4 5 6 7 8 9 10 11 12 | private class ImagePagerAdapter2 extends PagerAdapter { private int[] mImages = new int[] { R.drawable.add1, R.drawable.add3, R.drawable.add4, R.drawable.add2, }; @Override public float getPageWidth(int position) { return .3f; } |
调整返回值...少表示更多图像...... 0.3表示一次至少3张图像。
主要活动xml文件添加此代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <LinearLayout android:layout_width="wrap_content" android:layout_height="130dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:orientation="vertical" android:weightSum="1"> <RelativeLayout android:layout_width="match_parent" android:layout_height="130dp"> <com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer android:id="@+id/pager_container" android:layout_width="match_parent" android:layout_height="fill_parent"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="100dip" android:layout_height="100dip"/> </com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer> </RelativeLayout> </LinearLayout> |
主要活动代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | public class MainActivity extends Activity{ final Integer[] XMEN2= {R.mipmap.bookticket,R.mipmap.safty,R.mipmap.privacy}; private ArrayList<Integer> XMENArray2 = new ArrayList<Integer>(); PagerContainer mContainer; int currentPage2 = 0; private static int NUM_PAGES2 = 0; ViewPager mPager2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initData2();} private void initViews() { mPager2 = (ViewPager)findViewById(R.id.viewpager); mContainer = (PagerContainer)findViewById(R.id.pager_container); mPager2.setOffscreenPageLimit(5); mPager2.setPageMargin(15); mPager2.setClipChildren(false); } private void initData2() { for(int i=0;i<XMEN2.length;i++) XMENArray2.add(XMEN2[i]); mPager2.setAdapter(new Sliding_Adaptertwo(getActivity(),XMENArray2)); NUM_PAGES2 =XMEN2.length; final Handler handler = new Handler(); final Runnable Update = new Runnable() { public void run() { if (currentPage2 == NUM_PAGES2) { currentPage2= 0; }mPager2.setCurrentItem(currentPage2++, true); } }; Timer swipeTimer = new Timer(); swipeTimer.schedule(new TimerTask() { @Override public void run() { handler.post(Update); } }, 3000, 3000); } } |
Pager View pagercontainer类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | import android.content.Context; import android.graphics.Point; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener { private ViewPager mPager; boolean mNeedsRedraw = false; public PagerContainer(Context context) { super(context); init(); } public PagerContainer(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PagerContainer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { //Disable clipping of children so non-selected pages are visible setClipChildren(false); //Child clipping doesn't work with hardware acceleration in Android 3.x/4.x //You need to set this value here if using hardware acceleration in an // application targeted at these releases. setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override protected void onFinishInflate() { super.onFinishInflate(); try { mPager = (ViewPager) getChildAt(0); mPager.setOnPageChangeListener(this); } catch (Exception e) { throw new IllegalStateException("The root child of PagerContainer must be a ViewPager"); } } public ViewPager getViewPager() { return mPager; } private Point mCenter = new Point(); private Point mInitialTouch = new Point(); @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { mCenter.x = w / 2; mCenter.y = h / 2; } @Override public boolean onTouchEvent(MotionEvent ev) { //We capture any touches not already handled by the ViewPager // to implement scrolling from a touch outside the pager bounds. switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mInitialTouch.x = (int)ev.getX(); mInitialTouch.y = (int)ev.getY(); default: ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y); break; } return mPager.dispatchTouchEvent(ev); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { //Force the container to redraw on scrolling. //Without this the outer pages render initially and then stay static if (mNeedsRedraw) invalidate(); } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE); } } |
及其适配器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | public class Sliding_Adaptertwo extends PagerAdapter { private ArrayList<Integer> IMAGES; private LayoutInflater inflater; private Context context; public Sliding_Adaptertwo(Context context, ArrayList<Integer> IMAGES) { this.context = context; this.IMAGES=IMAGES; inflater = LayoutInflater.from(context); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public int getCount() { return IMAGES.size(); } @Override public Object instantiateItem(ViewGroup view, int position) { View imageLayout = inflater.inflate(R.layout.sliding_layout, view, false); assert imageLayout != null; final ImageView imageView = (ImageView) imageLayout .findViewById(R.id.image); imageView.setImageResource(IMAGES.get(position)); view.addView(imageLayout, 0); return imageLayout; } @Override public boolean isViewFromObject(View view, Object object) { return view.equals(object); } @Override public void restoreState(Parcelable state, ClassLoader loader) { } @Override public Parcelable saveState() { return null; } } |
适配器类的xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/image" android:layout_width="90dp" android:layout_height="90dp" android:adjustViewBounds="true" android:layout_gravity="center" android:scaleType="fitXY" android:src="@drawable/ad1" /> </FrameLayout> |
它工作正常
在使用此代码的xml文件中(主要活动)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <LinearLayout android:layout_width="wrap_content" android:layout_height="130dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:orientation="vertical" android:weightSum="1"> <RelativeLayout android:layout_width="match_parent" android:layout_height="130dp"> <com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer android:id="@+id/pager_container" android:layout_width="match_parent" android:layout_height="fill_parent"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="100dip" android:layout_height="100dip"/> </com.wonderla.wonderla.muthootpathanamthitta.activity_muthootpathanm.PagerContainer> </RelativeLayout> </LinearLayout> |
1 2 | LayoutParams lp = new LayoutParams(width,height); viewpager.setLayoutParams(lp); |