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


107

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

setPageMargin(-100);

Чи все-таки я можу показати також попередній перегляд лівої сторони? Це в основному щось схоже на віджет галереї, який я шукаю.


Гарне питання! Я нещодавно перевірив джерело, і я вважаю, що немає кращого способу, якщо ви не хочете змінювати код src. Чи setPageMargin(-100)працює робота правильно?
Макарс

GalleryView зробить цю роботу краще, якщо тільки ви не використовуєте ViewPger з фрагментами.
Алі АльНоаїмі

Я зміг це зробити за допомогою подання галереї. так само як viewpager будь-яким способом. не знаю, чому застаріла галерея
WillingLearner

Це питання з тих пір широко висвітлено у [публікації тут] [1] [1]: stackoverflow.com/questions/13914609/…
Бен Пірсон,

я використовую Vierpager з фрагментами. Отже, я можу використовувати такий же підхід?
asliyanage

Відповіді:


206

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

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

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

viewpager.setPageMargin(int);

2
Так , я згоден з вами Jiju Induchoodan .. Для отримання додаткової інформації , будь ласка , зверніться blog.neteril.org/blog/2013/10/14 / ... і stackoverflow.com/questions/13914609 / ...
Sripathi

Класно, це так просто :) Чи можна змінити розмір попереднього перегляду правого та лівого розмірів на сторінках перемикання сторінок перегляду? Наприклад - якщо фрагмент поза фокусом - його масштаб буде дорівнює 0,8, але коли ми перетягнемо його в центр - масштаб збільшиться до 1, а попередній фрагмент із центрального виду змінить масштаб до 0,8, коли вийдеш із екрана?
iamthevoid

Це працює! Але коли я намагаюся масштабувати макет центру, його масштабування вгорі та внизу. Ліворуч і праворуч не видно через прокладку. Будь ласка , дивіться питання stackoverflow.com/questions/52710076 / ...
Anooj Крішнан G

не працює з 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, який має дві PageTransformerреалізації, які можна використовувати як натхнення: https://developer.android.com/training/animation/screen-slide-2

Про новий ViewPager2


Ця ж проблема на oreo пристроях, запуску та закінчення прокладки працює, як очікувалося, на інших пристроях, але орео після ViewPager2. PageTransformer вирішив проблему, прокладки залишаються такими ж, і мені довелося додатиviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr

Я маю злегка перенести сторінку пейджера перегляду, щоб досягти цього ефекту
Мухаммед Сакіб

Неважливо, я забув додати цей рядок setOffscreenPageLimit(1):)
Мухаммед Сакіб

Це найкраще рішення, яке я коли-небудь знаходжу. Він прекрасно працює, але так, НЕ ЗАБУДУЙТЕ встановлювати ширину предмета ViewPager2, висоту MATCH_PARENT.
khushbu

26

У 2017 році такої поведінки додатково може бути легко досягнутий шляхом використання RecyclerViewз PagerSnapHelper (додано у версії 25.1.0 бібліотеки підтримки v7): 

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

Десь тому мені була потрібна така функція, схожа на переглядач, і я підготував крихітну бібліотеку:

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

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

Сподіваюся, що це комусь допоможе і заощадить кілька годин :)


Поза темою, тому що іноді потрібен лише пейджер, але приємно знати! Дякую, що поділились!
sud007

Це круто. У мене вже було багато помічників RecyclerView. Просто додаю просте, new PagerSnapHelper().attachToRecyclerView(recyclerView)і у мене є оснащення сторінки.
Стів

9

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


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
Я відмовився. вибач, брате. Це спрацювало цього разу !! Оновлено знову
шинхарський бансал

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

Можна або відключити крайовий ефект, встановивши android:overScrollMode="never"на панель перегляду, або виправити помилку за допомогою злегка зміненої версії класу EdgeEffect : виправлення ViewPagerEdgeEffect


-10

Використовуйте цей адаптер фрагментів та клас для перегляду вікна сторінок перегляду в лівій і правій прокрутці.

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

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