ViewPager з попередніми та наступними межами сторінки


144

Я проектую перегляд з декількох сторінок. Я хочу, щоб краї попередньої та наступної сторінок відображалися так, як нижче, і здійснити пальцем по 2 пальці для перемикання між сторінками.

введіть тут опис зображення

Я спробував використовувати ViewPagerнегативний запас сторінки, як пропонується тут, але це показує лише один край на екрані, а не обидва одночасно.

Як варіант, чи я можу розмістити частину свого зору поза екраном, а потім анімувати його, надаючи йому ViewPagerефект типу.

Як мені це робити? Дякую !


"показує лише один край на екрані, а не обидва одночасно." Ви на сторінці 0 і бачите лише частину сторінки 1? Можливо, вам потрібно використовувати круговий пейджер, наприклад, а потім завжди встановлювати свою сторінку в "середнє" положення. Дивіться цей пост і коментар: stackoverflow.com/a/8304474/1851478
logray

Відповіді:


100

Цитуючи себе з публікації в блозі на цю тему :

Третій підхід походить від Дейва Сміта, співавтора чудової книги Android Recipes. Він пішов у зовсім іншому напрямку, використовуючи спеціальний контейнер, який відключав відсікання дітей, щоб показувати більше однієї сторінки одночасно.

Його опублікований зразок коду показує всю дію. Його контейнер ( com.example.pagercontainer.PagerContainer) обгортає ViewPagerі закликає setClipChildren(false);до себе, так що, хоча ViewPagerфокус фокусується на одній вибраній сторінці, інші сторінки, що мають координати поза ViewPagerмежами, все ще видно, доки вони вміщуються в межах PagerContainer. Розміривши розмір, який ViewPagerмає бути меншим за розмір PagerContainer, ViewPagerможна розмістити його сторінки до цього розміру, залишаючи місце для перегляду інших сторінок. PagerContainer, однак, потрібно трохи допомогти із сенсорними подіями, оскільки вони ViewPagerбудуть обробляти лише пальці подій на власних видимих ​​межах, ігноруючи будь-які видимі сторони сторінок.

введіть тут опис зображення


1
Використовуючи це, я можу показати частину попередньої та наступної сторінки, як показано на зображенні вище, але тепер я не хочу показувати гострі краї на зображеннях. Я хочу, щоб вони розмивалися у напрямку до країв. Я використовую z-індекс для досягнення того ж
Shruti

2
@Shruti - просто додайте накладене зображення з потрібним ефектом
Даніель Л.

2
Я роблю те саме, але це вимикає ефект надмірної прокрутки для останнього елемента. Що-небудь веде до цього?
Сваям

1
@CommonsWare: Сер, я спробував ваше рішення! Це спрацювало досить добре. Overscroll є. Єдиною проблемою зараз є те, що наступна карта показує, але не попередню. Тобто, якщо я перебуваю на сторінці 2, я можу побачити сторінку 3, що визирає, але не сторінку 1. Де я міг помилитися?
Сваям

2
@Swayam: Я поняття не маю.
CommonsWare

110

У мене схоже рішення:

На панелі перегляду встановіть ліву та праву підкладку, наприклад 20dp. Встановіть також поле сторінки на панелі перегляду, наприклад, половину вкладки пейджера. І не забудьте відключити прокладку кліпів.

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

2
Гарне рішення надано.
akash89

найпростіший і найкращий спосіб
HannahCarney

Це відповідь звіра та звіра для розгляду іменних значень xd
silentsudo

1
бічна примітка: ця робота не працює з користувальницьким переглядом пейджера перегляду
votetez

@voytez будь-яке рішення для трансформатора?
Олексій

76
  1. Встановіть ліву і праву накладки для подання цілого предмета. Приклад xml (page_item.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"/>
    
    <TextView
        android:id="@+id/text1"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </LinearLayout>
    
  2. Потім встановіть від'ємний запас сторінки PageViewрівним 2 * (попереднє підкладка перегляду)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
    
  3. За бажанням. Встановіть нульову ліву підкладку для першого елемента та нульову праву підкладку для останнього, щоб приховати порожні краї. Ви можете зробити це в класі PageAdapterабо Pageфрагменті.


@Sergey, я не можу зробити цю роботу з вашим рішенням, чи можете ви розмістити приклад? thx
Marckaraujo

12
лише додавання примітки: якщо ви переходите зі сторінки 1 на сторінку 2, сторінка 3 не запам'ятовується, тому вона з’явиться із запізненням. щоб виправити це, просто додайте - yourViewPager.setOffscreenPageLimit (2);
Хосе Барбоса

Я роблю те саме, але це вимикає ефект надмірної прокрутки для останнього елемента. Що-небудь веде до цього?
Сваям

Я не можу зробити так, щоб це також працювало ... поля, схоже, відображаються випадковим чином, якщо я використовую зображення з масштабом, встановленим для центрального обрізання. У когось є приклад робочого коду, яким він може поділитися?
kenyee

2
Як торкнутися першого та останнього предмета? Перевіряючи індекс сторінки в OnPageListener?
Hardik9850

47

Для відображення попереднього перегляду лівої та правої сторінок встановіть наступні два значення

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

Якщо вам потрібен простір між двома сторінками в панелі перегляду, додайте viewpager.setPageMargin (int)

Android ViewPager - Показати попередній перегляд сторінки зліва та справа


3
Це має бути правильна відповідь. Я думаю, можливо, це не працювало в попередніх версіях viewpager, але воно працює зараз.
Грег Енніс

Його додавання однакового поля і в лівій частині першої, і в правій частині останньої сторінки. Будь-яке виправлення
Umesh Aawte

1
Коротка та більш чітка відповідь.
Імран Ахмед

10

якщо хтось все ще шукає рішення, я налаштував ViewPage, щоб досягти цього, не використовуючи негативну маржу, знайдіть зразок проекту тут https://github.com/44kksharma/Android-ViewPager-Carousel-UI, він повинен працювати в більшості випадків, але ви ще можна визначити поле сторінки за допомогою mPager.setPageMargin(margin in pixel);


1

Завантажте вихідний код звідси ( ViewPager з попередніми та наступними межами сторінки )

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

1
Цей код не працює належним чином, його показ на лівій сторінці трохи більший за правий
Chirag Joshi

1

Деякий час назад мені потрібна така особливість і підготував крихітну бібліотеку , яка використовує RecyclerViewз PagerSnapHelper (додано у версії 25.1.0 бібліотеки підтримки v7) замість класичного ViewPager:

MetalRecyclerPagerView - ви можете знайти весь код разом із прикладами там.

В основному він складається з файлу одного класу: MetalRecyclerViewPager.java (і двох xmls: attrs.xml та ids.xml ).

Сподіваюся, це комусь допоможе :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.