Android ViewPager - 在左侧和右侧显示页面预览
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10098040/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android ViewPager - Show preview of page on left and right
提问by Brian Boyle
I'm using Android's ViewPager
. What I want to do is to show a preview of the page on both the left and the right. I've seen where I can use a negative pageMargin
to show a preview of the right side.
我正在使用 Android 的ViewPager
. 我想要做的是在左侧和右侧显示页面预览。我已经看到可以使用负片pageMargin
来显示右侧预览的地方。
setPageMargin(-100);
Is there anyway that I can show a preview of the left side aswell? Its basically something similar to the gallery widget that I am looking for.
无论如何,我可以显示左侧的预览吗?它基本上类似于我正在寻找的画廊小部件。
回答by Jiju Induchoodan
To show preview of left and right pages set the following two values
要显示左右页面的预览,请设置以下两个值
viewpager.setClipToPadding(false);
viewpager.setPadding(left,0,right,0);
viewpager.setClipToPadding(false);
viewpager.setPadding(left,0,right,0);
If you need space between two pages in the viewpager then add
如果您在 viewpager 中的两个页面之间需要空间,则添加
viewpager.setPageMargin(int);
回答by Rohan Kandwal
The answer by @JijuInduchoodan is perfect and working. However, since I am relatively new to Android, it took me a while to understand & set it properly. So, I am posting this answer for future reference and help anyone else who is in same shoes as me.
@JijuInduchoodan 的答案是完美且有效的。但是,由于我对 Android 比较陌生,所以我花了一段时间来理解和正确设置它。因此,我发布此答案以供将来参考,并帮助与我处于同一位置的任何其他人。
if (viewPager == null)
{
// Initializing view pager
viewPager = (ViewPager) findViewById(R.id.vpLookBook);
// Disable clip to padding
viewPager.setClipToPadding(false);
// set padding manually, the more you set the padding the more you see of prev & next page
viewPager.setPadding(40, 0, 40, 0);
// sets a margin b/w individual pages to ensure that there is a gap b/w them
viewPager.setPageMargin(20);
}
There's no need to set any width to the ViewPager's
page in the adapter. There no additional code required to see previous & next page in ViewPager
. However, if you want to add blank space at the top & bottom of the each page, you can set the following code to ViewPager's
child page`s parent layout.
无需为ViewPager's
适配器中的页面设置任何宽度。在ViewPager
. 但是,如果您想在每个页面的顶部和底部添加空白区域,您可以将以下代码设置为ViewPager's
子页面的父布局。
android:paddingTop="20dp"
android:paddingBottom="20dp"
This will be the final look of the ViewPager.
这将是 ViewPager 的最终外观。
回答by Albert Vila Calvo
Solution with the new ViewPager2
新的 ViewPager2 解决方案
Nowadays you should consider using ViewPager2which "replaces ViewPager, addressing most of its predecessor's pain-points":
现在你应该考虑使用ViewPager2,它“取代了 ViewPager,解决了它前辈的大部分痛点”:
- Based on RecyclerView
- RTL (right-to-left) layout support
- Vertical orientation support
- Reliable Fragment support (including handling changes to the underlying Fragment collection)
- Dataset change animations (including
DiffUtil
support)
- 基于 RecyclerView
- RTL(从右到左)布局支持
- 垂直方向支持
- 可靠的 Fragment 支持(包括处理对底层 Fragment 集合的更改)
- 数据集更改动画(包括
DiffUtil
支持)
The result
结果
The code
编码
In your Activity/Fragment, setup the ViewPager2:
在您的活动/片段中,设置 ViewPager2:
// MyRecyclerViewAdapter is an standard RecyclerView.Adapter :)
viewPager2.adapter = MyRecyclerViewAdapter()
// You need to retain one page on each side so that the next and previous items are visible
viewPager2.offscreenPageLimit = 1
// Add a PageTransformer that translates the next and previous items horizontally
// towards the center of the screen, which makes them visible
val nextItemVisiblePx = resources.getDimension(R.dimen.viewpager_next_item_visible)
val currentItemHorizontalMarginPx = resources.getDimension(R.dimen.viewpager_current_item_horizontal_margin)
val pageTranslationX = nextItemVisiblePx + currentItemHorizontalMarginPx
val pageTransformer = ViewPager2.PageTransformer { page: View, position: Float ->
page.translationX = -pageTranslationX * position
// Next line scales the item's height. You can remove it if you don't want this effect
page.scaleY = 1 - (0.25f * abs(position))
// If you want a fading effect uncomment the next line:
// page.alpha = 0.25f + (1 - abs(position))
}
viewPager2.setPageTransformer(pageTransformer)
// The ItemDecoration gives the current (centered) item horizontal margin so that
// it doesn't occupy the whole screen width. Without it the items overlap
val itemDecoration = HorizontalMarginItemDecoration(
context,
R.dimen.viewpager_current_item_horizontal_margin
)
viewPager2.addItemDecoration(itemDecoration)
Add the HorizontalMarginItemDecoration
, which is a trivial ItemDecoration
:
添加HorizontalMarginItemDecoration
,这是一个微不足道的ItemDecoration
:
/**
* Adds margin to the left and right sides of the RecyclerView item.
* Adapted from https://stackoverflow.com/a/27664023/4034572
* @param horizontalMarginInDp the margin resource, in dp.
*/
class HorizontalMarginItemDecoration(context: Context, @DimenRes horizontalMarginInDp: Int) :
RecyclerView.ItemDecoration() {
private val horizontalMarginInPx: Int =
context.resources.getDimension(horizontalMarginInDp).toInt()
override fun getItemOffsets(
outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
) {
outRect.right = horizontalMarginInPx
outRect.left = horizontalMarginInPx
}
}
Add the dimensions that control how much of the previous/next item is visible, and current item horizontal margin:
添加控制上一个/下一个项目的可见程度和当前项目水平边距的尺寸:
<dimen name="viewpager_next_item_visible">26dp</dimen>
<dimen name="viewpager_current_item_horizontal_margin">42dp</dimen>
Finally add the ViewPager2
to your layout:
最后添加ViewPager2
到您的布局:
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
One important thing: a ViewPager2
item must have layout_height="match_parent"
(otherwise it throws an IllegalStateException), so you should do something like:
一件重要的事情:一个ViewPager2
项目必须有layout_height="match_parent"
(否则它会抛出一个 IllegalStateException),所以你应该这样做:
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" <-- this!
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="280dp">
<!-- ... -->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
PageTransformer examples
PageTransformer 示例
Google has added a guide on ViewPager2 that has 2 PageTransformer
implementations that you can use as an inspiration: https://developer.android.com/training/animation/screen-slide-2
Google 在 ViewPager2 上添加了一个指南,其中有 2 个PageTransformer
您可以用作灵感的实现:https: //developer.android.com/training/animation/screen-slide-2
About the new ViewPager2
关于新的 ViewPager2
回答by Alexander Bilchuk
In 2017 such behaviour additionally can be easily achieved by using RecyclerView
with PagerSnapHelper(added in version 25.1.0 of v7 support library):
?
在2017年这样的行为还可以通过使用容易地实现RecyclerView
与PagerSnapHelper(在第7版支持库的版本25.1.0加入):
Sometime ago I needed such viewpager-like feature and prepared a tiny library:
前段时间我需要这种类似 viewpager 的功能并准备了一个小库:
MetalRecyclerPagerView- you can find all the code along with examples there.
MetalRecyclerPagerView- 您可以在那里找到所有代码和示例。
Mainly it consists of a single class file: MetalRecyclerViewPager.java(and two xmls: attrs.xmland ids.xml).
它主要由一个类文件组成:MetalRecyclerViewPager.java(以及两个xml:attrs.xml和ids.xml)。
Hope it helps somebody and will save some hours :)
希望它可以帮助某人并节省一些时间:)
回答by 44kksharma
if someone still looking for solution, I had customized the ViewPage to achieve it without using negative margin, find a sample project here https://github.com/44kksharma/Android-ViewPager-Carousel-UIit should work in most cases but you can still define page margin with
mPager.setPageMargin(margin in pixel);
如果有人仍在寻找解决方案,我已经自定义了 ViewPage 以在不使用负边距的情况下实现它,请在此处找到示例项目https://github.com/44kksharma/Android-ViewPager-Carousel-UI在大多数情况下它应该可以工作,但您仍然可以定义页边距
mPager.setPageMargin(margin in pixel);
回答by sma6871
You can do this in xml file, just use below code:
您可以在 xml 文件中执行此操作,只需使用以下代码:
android:clipToPadding="false"
android:paddingLeft="XX"
android:paddingRight="XX"
For example:
例如:
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingLeft="30dp"
android:paddingRight="30dp" />
Note: If you need space between pages, set padding/margin to child fragments
注意:如果您需要页面之间的空间,请将填充/边距设置为子片段
回答by Saurabh Verma
For those struggling to have this on different screens,
对于那些努力在不同屏幕上拥有它的人来说,
mPager.setClipToPadding(false);
DisplayMetrics displayMetrics = new DisplayMetrics();
self.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int paddingToSet = width/4; //set this ratio according to how much of the next and previos screen you want to show.
mPager.setPadding(paddingToSet,0,paddingToSet,0);
回答by ssynhtn
Note that when setting none zero paddings to a viewpager, the viewpager's edgeeffect placement is messed up, this is a bug of the viewpager, see here:viewpager edgeeffect bug
请注意,当为viewpager设置none zero paddings时,viewpager的edgeeffect位置被搞乱了,这是viewpager的一个bug,请看这里:viewpager edgeeffect bug
You can either disable the edge effect by setting android:overScrollMode="never"
to the viewpager, or you can fix the bug with a slightly modified version of the EdgeEffect class:ViewPagerEdgeEffect fix
您可以通过设置android:overScrollMode="never"
viewpager来禁用边缘效果,或者您可以使用 EdgeEffect 类的稍微修改版本修复该错误:ViewPagerEdgeEffect fix
回答by Veerababu Medisetti
Use this fragment adapter and class to view the viewpager in left and right scroll.add necessary classes to scroll to view next pages.
使用此片段适配器和类在左右滚动中查看 viewpager。添加必要的类以滚动查看下一页。
package com.rmn.viewpager;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
/**
* The <code>PagerAdapter</code> serves the fragments when paging.
* @author mwho
*/
public class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
/**
* @param fm
* @param fragments
*/
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/* (non-Javadoc)
* @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
/* (non-Javadoc)
* @see android.support.v4.view.PagerAdapter#getCount()
*/
@Override
public int getCount() {
return this.fragments.size();
}
}
package com.manishkpr.viewpager;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context _context;
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
_context=context;
}
@Override
public Fragment getItem(int position) {
Fragment f = new Fragment();
switch(position){
case 0:
f=LayoutOne.newInstance(_context);
break;
case 1:
f=LayoutTwo.newInstance(_context);
break;
}
return f;
}
@Override
public int getCount() {
return 2;
}
}