具有上一页和下一页边界的 ViewPager

Posted

技术标签:

【中文标题】具有上一页和下一页边界的 ViewPager【英文标题】:ViewPager with previous and next page boundaries 【发布时间】:2012-12-04 13:48:34 【问题描述】:

我正在设计一个包含多个页面的视图。我希望上一页和下一页的边缘如下所示,并实现两指滑动以在页面之间切换。

我尝试按照here 的建议使用带有负页边距的ViewPager,但它只显示屏幕上的一个边缘,而不是同时显示两个。

或者,有什么方法可以将我的视图的一部分放置在屏幕外,然后对其进行动画处理,使其具有ViewPager 类型的效果。

我应该怎么做?谢谢!

【问题讨论】:

"只在屏幕上显示一个边缘,而不是同时显示两个。"您在第 0 页上,而您只看到第 1 页的一部分吗?也许您需要使用循环寻呼机,例如,然后将您的页面始终设置为“中间”位置。看到这篇文章和评论:***.com/a/8304474/1851478 【参考方案1】:

我有类似的解决方案:

在 viewpager 上设置左右填充,例如20dp。还要在 viewpager 上设置页边距,例如寻呼机填充的一半。并且不要忘记禁用剪辑填充。

tilePager.setPadding(defaultGap, 0, defaultGap, 0);
tilePager.setClipToPadding(false);
tilePager.setPageMargin(halfGap);

【讨论】:

提供了很好的解决方案。 最简单最好的方法 这是考虑命名值 xd 的野兽是野兽的答案 旁注:这不适用于自定义视图寻呼机转换器 @voytez 变压器的任何解决方案?【参考方案2】:

从a blog post on this subject引用我自己的话:

第三种方法来自著名书籍 android 食谱的合著者 Dave Smith。他采用了一个非常不同的方向,使用了一个自定义容器,该容器禁止儿童剪辑以一次显示多个页面。

他的published sample code 展示了整个过程。他的容器 (com.example.pagercontainer.PagerContainer) 包装了ViewPager 并在其自身上调用setClipChildren(false);,因此即使ViewPager 专注于一个选定的页面,坐标超出ViewPager 边界的其他页面仍然可见,所以只要它们适合PagerContainer。通过将ViewPager 的大小设置为小于PagerContainerViewPager 可以将其页面调整为该大小,从而为其他页面留出空间。不过,PagerContainer 需要在触摸事件方面提供一些帮助,因为ViewPager 只会在其可见范围内处理滑动事件,而忽略任何侧面可见的页面。

【讨论】:

通过使用它,我可以显示上一页和下一页的一部分,如上图所示,但现在我不想在图像上显示锐利的边缘。我希望它们向边缘模糊..请指导我如何使用 z-index 来实现同样的目标 @Shruti - 只需添加具有您想要的效果的叠加图像 我也这样做,但它禁用了最后一项的过度滚动效果。有什么线索吗? @CommonsWare :先生,我尝试了您的解决方案!它工作得很好。过度滚动在那里。现在唯一的问题是下一张卡片显示,而不是前一张卡片。也就是说,如果我在第 2 页,我可以看到第 3 页向外窥视,但看不到第 1 页。我哪里出错了? @Swayam:我不知道。【参考方案3】:

    为整个项目视图设置左右填充。示例 xml (page_item.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"/>
    
    <TextView
        android:id="@+id/text1"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </LinearLayout>
    

    然后将PageView 的负页边距设置为等于 2*(上一个视图填充)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
    

    可选。为第一项设置零左填充,为最后一项设置零右填充以隐藏空白边缘。您可以在 PageAdapterPage 片段类中执行此操作。

【讨论】:

@Sergey,我无法使用您的解决方案进行此操作,您可以发布一个示例吗?谢谢 只是添加一个注释:使用此解决方案,当您从第 1 页滑到第 2 页时,第 3 页不在内存中,因此会延迟显示。要解决这个问题,只需添加 - yourViewPager.setOffscreenPageLimit(2); 我也这样做,但它禁用了最后一项的过度滚动效果。有什么线索吗? 我似乎也无法使其正常工作...如果我使用带有比例设置为中心裁剪的图像,边距似乎随机显示。谁有可以分享的工作代码示例? 如何触摸第一项和最后一项?通过检查 OnPageListener 中的页面索引?【参考方案4】:

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

viewpager.setClipToPadding(false)
viewpager.setPadding(left,0,right,0)

如果您需要在 viewpager 中的两个页面之间留出空间,则添加 viewpager.setPageMargin(int)

Android ViewPager - Show preview of page on left and right

【讨论】:

这应该是正确的答案。我想也许这在以前版本的 viewpager 中不起作用,但现在可以了。 它在第一页的左侧和最后一页的右侧添加相同的边距。任何修复 简短而清晰的答案。【参考方案5】:

如果有人还在寻找解决方案,我已经自定义了 ViewPage 以在不使用负边距的情况下实现它,请在此处找到示例项目 https://github.com/44kksharma/Android-ViewPager-Carousel-UI 它应该在大多数情况下工作,但您仍然可以定义页边距 mPager.setPageMargin(margin in pixel);

【讨论】:

谢谢。如何增加页面间距? mPager.setPageMargin(margin in pixel);【参考方案6】:

从这里下载源代码(ViewPager with previous and next page boundaries)

MainActivity.java

package com.deepshikha.viewpager;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends FragmentActivity 

    ViewPager pager;
    MyPageAdapter obj_adapter;
    String str_device;

    @Override

    public void onCreate(Bundle savedInstanceState) 

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();


    

    private void init() 
        pager = (ViewPager) findViewById(R.id.viewpager);
        differentDensityAndScreenSize(getApplicationContext());
        List<Fragment> fragments = getFragments();
        pager.setAdapter(obj_adapter);
        pager.setClipToPadding(false);


        if (str_device.equals("normal-hdpi"))
            pager.setPadding(160, 0, 160, 0);
        else if (str_device.equals("normal-mdpi"))
            pager.setPadding(160, 0, 160, 0);
        else if (str_device.equals("normal-xhdpi"))
            pager.setPadding(160, 0, 160, 0);
        else if (str_device.equals("normal-xxhdpi"))
            pager.setPadding(180, 0, 180, 0);
        else if (str_device.equals("normal-xxxhdpi"))
            pager.setPadding(180, 0, 180, 0);
        else if (str_device.equals("normal-unknown"))
            pager.setPadding(160, 0, 160, 0);
        else 

        

        obj_adapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        pager.setPageTransformer(true, new ExpandingViewPagerTransformer());
        pager.setAdapter(obj_adapter);
    

    class MyPageAdapter extends FragmentPagerAdapter 

        private List<Fragment> fragments;

        public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) 

            super(fm);

            this.fragments = fragments;

        

        @Override

        public Fragment getItem(int position) 

            return this.fragments.get(position);

        

        @Override

        public int getCount() 

            return this.fragments.size();

        

    

    private List<Fragment> getFragments() 

        List<Fragment> fList = new ArrayList<Fragment>();

        fList.add(MyFragment.newInstance("Fragment 1",R.drawable.imags));
        fList.add(MyFragment.newInstance("Fragment 2",R.drawable.image1));
        fList.add(MyFragment.newInstance("Fragment 3",R.drawable.image2));
        fList.add(MyFragment.newInstance("Fragment 4",R.drawable.image3));
        fList.add(MyFragment.newInstance("Fragment 5",R.drawable.image4));

        return fList;

    

    public int differentDensityAndScreenSize(Context context) 
        int value = 20;
        String str = "";
        if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) 
            switch (context.getResources().getDisplayMetrics().densityDpi) 
                case DisplayMetrics.DENSITY_LOW:
                    str = "small-ldpi";
                    // Log.e("small 1","small-ldpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "small-mdpi";
                    // Log.e("small 1","small-mdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    str = "small-hdpi";
                    // Log.e("small 1","small-hdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    str = "small-xhdpi";
                    // Log.e("small 1","small-xhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    str = "small-xxhdpi";
                    // Log.e("small 1","small-xxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    str = "small-xxxhdpi";
                    //Log.e("small 1","small-xxxhdpi");
                    value = 20;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    str = "small-tvdpi";
                    // Log.e("small 1","small-tvdpi");
                    value = 20;
                    break;
                default:
                    str = "small-unknown";
                    value = 20;
                    break;
            

         else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) 
            switch (context.getResources().getDisplayMetrics().densityDpi) 
                case DisplayMetrics.DENSITY_LOW:
                    str = "normal-ldpi";
                    // Log.e("normal-ldpi 1","normal-ldpi");
                    str_device = "normal-ldpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("normal-mdpi 1","normal-mdpi");
                    str = "normal-mdpi";
                    value = 82;
                    str_device = "normal-mdpi";
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    // Log.e("normal-hdpi 1","normal-hdpi");
                    str = "normal-hdpi";
                    str_device = "normal-hdpi";
                    value = 82;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    //Log.e("normal-xhdpi 1","normal-xhdpi");
                    str = "normal-xhdpi";
                    str_device = "normal-xhdpi";
                    value = 90;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("normal-xxhdpi 1","normal-xxhdpi");
                    str = "normal-xxhdpi";
                    str_device = "normal-xxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    //Log.e("normal-xxxhdpi","normal-xxxhdpi");
                    str = "normal-xxxhdpi";
                    str_device = "normal-xxxhdpi";
                    value = 96;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("DENSITY_TV 1","normal-mdpi");
                    str = "normal-tvdpi";
                    str_device = "normal-tvmdpi";
                    value = 96;
                    break;
                default:
                    // Log.e("normal-unknown","normal-unknown");
                    str = "normal-unknown";
                    str_device = "normal-unknown";
                    value = 82;
                    break;
            
         else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) 
            switch (context.getResources().getDisplayMetrics().densityDpi) 
                case DisplayMetrics.DENSITY_LOW:
                    str = "large-ldpi";
                    // Log.e("large-ldpi 1","normal-ldpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    str = "large-mdpi";
                    //Log.e("large-ldpi 1","normal-mdpi");
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "large-hdpi";
                    value = 78;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-xhdpi");
                    str = "large-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    //Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "large-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "large-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("large-ldpi 1","normal-tvdpi");
                    str = "large-tvdpi";
                    value = 125;
                    break;
                default:
                    str = "large-unknown";
                    value = 78;
                    break;
            

         else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) 
            switch (context.getResources().getDisplayMetrics().densityDpi) 
                case DisplayMetrics.DENSITY_LOW:
                    // Log.e("large-ldpi 1","normal-ldpi");
                    str = "xlarge-ldpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    // Log.e("large-ldpi 1","normal-mdpi");
                    str = "xlarge-mdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    //Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-hdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    // Log.e("large-ldpi 1","normal-hdpi");
                    str = "xlarge-xhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    // Log.e("large-ldpi 1","normal-xxhdpi");
                    str = "xlarge-xxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_XXXHIGH:
                    // Log.e("large-ldpi 1","normal-xxxhdpi");
                    str = "xlarge-xxxhdpi";
                    value = 125;
                    break;
                case DisplayMetrics.DENSITY_TV:
                    //Log.e("large-ldpi 1","normal-tvdpi");
                    str = "xlarge-tvdpi";
                    value = 125;
                    break;
                default:
                    str = "xlarge-unknown";
                    value = 125;
                    break;
            
        

        return value;
    

【讨论】:

这段代码不能正常工作,它显示的左边页面比右边大一点【参考方案7】:

前段时间我需要这样的功能并准备了一个小型库,它使用 RecyclerView 和 PagerSnapHelper(在 v7 支持库的 25.1.0 版本中添加)而不是经典的 ViewPager

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

主要由一个类文件组成:MetalRecyclerViewPager.java(和两个 xml:attrs.xml 和 ids.xml)。

希望它可以帮助某人:)

【讨论】:

【参考方案8】:

轮播 ViewPager 片段

    ViewPager viewPager = findViewById(R.id.viewPager);
    TabPagerAdapter tabPagerAdapter = new TabPagerAdapter(this,getSupportFragmentManager());
    viewPager.setAdapter(tabPagerAdapter);
    // 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的主要内容,如果未能解决你的问题,请参考以下文章

wordpress 如何在子页面中导航上一页和下一页

php WordPress |自定义上一页和下一页链接

laravel5.5中添加对分页样式的修改上一页和下一页

使用session处理用户搜索后数据的上一页和下一页跳转

word编辑过程中格式突然变了,上一页和下一页的不一致怎么办?

laravel写出文章的上一篇和下一篇并进行MySQL语句性能测试