Android ViewPager - Pokaż podgląd strony po lewej i po prawej stronie

107

Używam Androida ViewPager. Chcę tylko pokazać podgląd strony po lewej i po prawej stronie. Widziałem, gdzie mogę użyć negatywu, pageMarginaby wyświetlić podgląd prawej strony.

setPageMargin(-100);

Czy w ogóle mogę wyświetlić podgląd lewej strony? Jest to w zasadzie coś podobnego do widżetu galerii, którego szukam.

Brian Boyle
źródło
Dobre pytanie! Niedawno sprawdziłem źródło i czuję, że nie ma lepszego sposobu, jeśli nie chcesz modyfikować kodu src. Czy setPageMargin(-100)działa poprawnie?
Macarse
GalleryView wykona pracę lepiej, chyba że używasz ViewPger z fragmentami.
Ali AlNoaimi
Udało mi się to zrobić za pomocą widoku galerii. tak samo jak viewpager w żaden sposób. nie wiem, dlaczego galeria jest przestarzała
WillingLearner
To pytanie zostało od tego czasu obszernie omówione w [post tutaj] [1] [1]: stackoverflow.com/questions/13914609/…
Ben Pearson
używam Vierpagera z fragmentami, więc czy mogę zastosować to samo podejście?
asliyanage

Odpowiedzi:

206

Aby wyświetlić podgląd lewej i prawej strony, ustaw następujące dwie wartości

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

Jeśli potrzebujesz odstępu między dwiema stronami w podglądzie, dodaj

viewpager.setPageMargin(int);
Jiju Induchoodan
źródło
2
Tak, zgadzam się z tobą Jiju Induchoodan .. Aby uzyskać więcej informacji, odwiedź blog.neteril.org/blog/2013/10/14/ ... i stackoverflow.com/questions/13914609/ ...
Sripathi
Fajnie, to takie proste :) Czy jest możliwość zmiany rozmiaru podglądu dla prawego i lewego rozmiaru na przełączanych stronach widoku pagera? Na przykład - jeśli fragment jest nieostry - jego skala będzie wynosić ~ 0,8, ale gdy przeciągniemy go do środka - skala wzrośnie do 1, a poprzedni fragment z widoku środkowego zmieni skalę na 0,8, wychodząc poza ekran?
iamthevoid
To działa! Ale kiedy próbuję powiększyć układ środkowy, powiększa się do góry i do dołu. Lewa i prawa strona nie są widoczne ze względu na wypełnienie. Zobacz pytanie stackoverflow.com/questions/52710076/…
Anooj Krishnan G
nie działa z przeglądarką 2
hamiid reza Gholami
73

Odpowiedź @JijuInduchoodan jest doskonała i działa. Jednak ponieważ jestem stosunkowo nowy w Androidzie, zajęło mi trochę czasu, aby zrozumieć i ustawić go prawidłowo. Dlatego zamieszczam tę odpowiedź do wykorzystania w przyszłości i pomagam każdemu, kto jest w tym samym miejscu co ja.

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

Nie ma potrzeby ustawiania żadnej szerokości ViewPager'sstrony w adapterze. Nie jest wymagany żaden dodatkowy kod, aby wyświetlić poprzednią i następną stronę ViewPager. Jeśli jednak chcesz dodać puste miejsce na górze i na dole każdej strony, możesz ustawić następujący kod na ViewPager'sukład nadrzędny strony podrzędnej.

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

Final ViewPager

To będzie ostateczny wygląd ViewPagera.

Rohan Kandwal
źródło
62

Rozwiązanie z nowym ViewPager2

W dzisiejszych czasach powinieneś rozważyć użycie ViewPager2, który „zastępuje ViewPager, rozwiązując większość problemów jego poprzednika” :

  • Na podstawie RecyclerView
  • Obsługa układu RTL (od prawej do lewej)
  • Wsparcie orientacji pionowej
  • Niezawodna obsługa fragmentów (w tym obsługa zmian w podstawowej kolekcji fragmentów)
  • Animacje zmiany zbioru danych (w tym DiffUtilwsparcie)

Wynik

wprowadź opis obrazu tutaj

Kod

W swojej aktywności / fragmencie skonfiguruj 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)

Dodaj HorizontalMarginItemDecoration, co jest trywialne 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
    }

}

Dodaj wymiary, które kontrolują, jaka część poprzedniego / następnego elementu jest widoczna, oraz poziomy margines bieżącego elementu:

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

wprowadź opis obrazu tutaj

Na koniec dodaj ViewPager2do swojego układu:

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

Jedna ważna rzecz: ViewPager2element musi mieć layout_height="match_parent"(w przeciwnym razie rzuca wyjątek IllegalStateException), więc powinieneś zrobić coś takiego:

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

Przykłady PageTransformera

Google dodał przewodnik po ViewPager2, który ma 2 PageTransformerimplementacje, których możesz użyć jako inspiracji: https://developer.android.com/training/animation/screen-slide-2

O nowym ViewPager2

Albert Vila Calvo
źródło
Ten sam problem na urządzeniach oreo, dopełnienie początku i końca działa zgodnie z oczekiwaniami na innych urządzeniach, ale oreo po ViewPager2. PageTransformer rozwiązał problem, wyściółki są nadal takie same i musiałem dodaćviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr
Muszę lekko przesunąć stronę widoku, aby uzyskać ten efekt
Muhammad Saqib
nieważne, zapomniałem dodać tę linię setOffscreenPageLimit(1):)
Muhammad Saqib
To najlepsze rozwiązanie, jakie kiedykolwiek znalazłem. Działa doskonale, ale tak, NIE ZAPOMNIJ ustawić szerokość i wysokość elementu ViewPager2 na MATCH_PARENT.
khushbu
26

W 2017 r takiego działania dodatkowo może być łatwo osiągnięty za pomocą RecyclerViewz PagerSnapHelper (wersja 25.1.0 dodano biblioteki nośnej V7) 

wprowadź opis obrazu tutaj

Jakiś czas temu potrzebowałem funkcji przypominającej przeglądarkę i przygotowałem małą bibliotekę:

MetalRecyclerPagerView - możesz tam znaleźć cały kod wraz z przykładami.

Głównie składa się z jednego pliku klasy: MetalRecyclerViewPager.java (oraz dwóch plików xml: attrs.xml i ids.xml ).

Mam nadzieję, że to komuś pomoże i pozwoli zaoszczędzić kilka godzin :)

Aleksandra Bilczuka
źródło
Poza tematem, ponieważ czasami potrzebny jest tylko pager, ale dobrze wiedzieć! Dzięki za udostępnienie!
sud007
To jest niesamowite. Miałem już mnóstwo kodu pomocniczego RecyclerView. Po prostu dodaję proste new PagerSnapHelper().attachToRecyclerView(recyclerView)i mam przyciąganie stron.
Steve
9

jeśli ktoś nadal szuka rozwiązania, dostosowałem ViewPage, aby osiągnąć to bez użycia ujemnego marginesu, przykładowy projekt znajdziesz tutaj https://github.com/44kksharma/Android-ViewPager-Carousel-UI powinien działać w większości przypadków ale Ty nadal można zdefiniować margines strony za pomocą mPager.setPageMargin(margin in pixel);

44kksharma
źródło
7

Możesz to zrobić w pliku xml, po prostu użyj poniższego kodu:

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

Na przykład:

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

Uwaga: jeśli potrzebujesz odstępu między stronami, ustaw dopełnienie / marginesy na fragmenty podrzędne

sma6871
źródło
3
Głosowałem w dół. przepraszam bracie. Tym razem zadziałało !! Głosowano ponownie
shikhar bansal
1

Dla tych, którzy mają problemy z wyświetlaniem tego na różnych ekranach,

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

Saurabh Verma
źródło
0

Zauważ, że przy ustawianiu żadnych zerowych wypełnień na stronie podglądu, umieszczenie efektu krawędzi jest pomieszane, jest to błąd przeglądarki, zobacz tutaj: błąd efektu krawędzi widoku strony

Możesz albo wyłączyć efekt krawędzi, ustawiając android:overScrollMode="never"przeglądarkę, albo możesz naprawić błąd za pomocą nieznacznie zmodyfikowanej wersji klasy EdgeEffect : poprawka ViewPagerEdgeEffect

ssynhtn
źródło
-10

Użyj tego adaptera fragmentu i klasy, aby wyświetlić przeglądarkę w przewijaniu w lewo i w prawo. Dodaj niezbędne klasy, aby przewijać, aby wyświetlić następne strony.

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

}
Veerababu Medisetti
źródło