Android ViewPager-在左右显示页面预览


107

我正在使用Android的ViewPager。我要做的是在左右两边都显示页面的预览。我已经看到可以在底片pageMargin上显示右侧预览的地方。

setPageMargin(-100);

无论如何,我还能显示左侧的预览吗?它基本上类似于我正在寻找的Gallery小部件。


好问题!我最近检查了源代码,如果您不想修改src代码,我觉得没有更好的方法。是否setPageMargin(-100)工作正常?
Macarse'4

除非您使用带有片段的ViewPger,否则GalleryView会做得更好。
Ali AlNoaimi 2012年

我能够使用图库视图来做到这一点。与viewpager完全相同。不知道为什么不推荐使用画廊
WillingLearner 2012年

这个问题已经被广泛报道[张贴在这里] [1] [1]:stackoverflow.com/questions/13914609/...
本·皮尔逊

我在Vierpager中使用fragment.So,我可以使用相同的方法吗?
asliyanage,2015年

Answers:


206

要显示左右页面的预览,请设置以下两个值

  1. viewpager.setClipToPadding(false);
  2. viewpager.setPadding(left,0,right,0);

如果您需要在viewpager中的两个页面之间放置空格,请添加

viewpager.setPageMargin(int);

2
是的,我同意你挤车Induchoodan ..欲了解更多信息,请参阅blog.neteril.org/blog/2013/10/14/...stackoverflow.com/questions/13914609/...
Sripathi

太酷了,它是如此简单:)是否可以在视图分页器的切换页面上以左右尺寸调整预览大小?例如-如果片段未聚焦-它的比例将为〜0.8,但是当我们将其拖动到中心时-比例将增加为1,而离开屏幕时,来自中心视图的先前片段将比例更改为0.8?
iamthevoid

工作正常!但是,当我尝试缩放中心布局时,它会缩放到顶部和底部。由于填充,左右不可见。请参阅问题stackoverflow.com/questions/52710076/...
Anooj克里希南摹

不能与viewpager 2一起使用
hamiid reza Gholami

73

@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);
        }

无需为ViewPager's适配器中的页面设置任何宽度。不需要其他代码即可查看中的上一页和下一页ViewPager。但是,如果要在每个页面的顶部和底部添加空格,则可以将以下代码设置为ViewPager's子页面的父布局。

android:paddingTop="20dp"
android:paddingBottom="20dp"

最终ViewPager

这将是ViewPager的最终外观。


62

新的ViewPager2解决方案

如今,您应该考虑使用ViewPager2,它“取代了ViewPager,解决了其前任的大部分难题”

  • 基于RecyclerView
  • RTL(从右到左)布局支持
  • 垂直方向支撑
  • 可靠的片段支持(包括处理对基础片段集合的更改)
  • 数据集更改动画(包括DiffUtil支持)

结果

在此处输入图片说明

代码

在您的活动/片段中,设置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)

添加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
    }

}

添加尺寸以控制可见的上一个/下一个项目以及当前项目的水平边距:

<dimen name="viewpager_next_item_visible">26dp</dimen>
<dimen name="viewpager_current_item_horizontal_margin">42dp</dimen>

在此处输入图片说明

最后将放入ViewPager2您的布局:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

重要事项:某项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示例

Google在ViewPager2上添加了一个指南,其中包含2种PageTransformer实现方式,您可以从中获得启发:https : //developer.android.com/training/animation/screen-slide-2

关于新的ViewPager2


在oreo设备上存在相同的问题,填充起点和终点在其他设备上按预期方式工作,但在ViewPager2之后是oreo。PageTransformer解决了该问题,填充仍然相同,我不得不添加viewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr

我必须稍微移动视图寻呼机的页面才能获得此效果
Muhammad Saqib

没关系,我忘了添加此行setOffscreenPageLimit(1):)
Muhammad Saqib

这是我找到的最好的解决方案。它可以正常工作,但是可以,请不要将ViewPager2的项目宽度,高度设置为MATCH_PARENT。
khushbu

26

在2017年,可以通过RecyclerViewPagerSnapHelper(在v7支持库的版本25.1.0中添加)一起轻松实现这种行为:

在此处输入图片说明

不久前,我需要类似viewpager的功能并准备了一个小库:

MetalRecyclerPagerView-您可以在此处找到所有代码以及示例。

它主要包含一个类文件:MetalRecyclerViewPager.java(和两个xmlattrs.xmlids.xml)。

希望它可以帮助某人并节省一些时间:)


不在主题之列,因为有时只需要寻呼机,但是很高兴知道!感谢分享!
sud007

这太棒了。我已经有很多RecyclerView帮助程序代码。只需添加一个简单的new PagerSnapHelper().attachToRecyclerView(recyclerView)页面即可。
史蒂夫(Steve)


7

您可以在xml文件中执行此操作,只需使用以下代码即可:

 android:clipToPadding="false"
 android:paddingLeft="XX"
 android:paddingRight="XX"

例如:

<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" />

注意:如果页面之间需要空格,请将填充/边距设置为子片段


3
我投票了。兄弟抱歉。这次成功了!!再次被支持
shikhar bansal 19/09/17

1

对于那些努力在不同屏幕上显示的用户,

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

0

请注意,当没有为viewpager设置零填充时,viewpager的edgeeffect位置被弄乱了,这是viewpager的bug,请参见此处:viewpager edgeeffect bug

您可以通过设置android:overScrollMode="never"为viewpager 来禁用边缘效果,也可以使用EdgeEffect类的稍作修改的版本来修复该错误:ViewPagerEdgeEffect修复


-10

使用此片段适配器和类可在左右滚动条中查看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;
    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.