Android ViewPager: mostra l'anteprima della pagina a sinistra ea destra


107

Sto usando Android ViewPager. Quello che voglio fare è mostrare un'anteprima della pagina sia a sinistra che a destra. Ho visto dove posso usare un negativo pageMarginper mostrare un'anteprima del lato destro.

setPageMargin(-100);

C'è comunque che posso mostrare un'anteprima anche del lato sinistro? È fondamentalmente qualcosa di simile al widget della galleria che sto cercando.


Buona domanda! Ho recentemente controllato i sorgenti e credo che non ci sia modo migliore se non vuoi modificare il codice src. Funziona setPageMargin(-100)correttamente?
Macarse

GalleryView farà il lavoro meglio, a meno che non si utilizzi ViewPger con frammenti.
Ali AlNoaimi

Sono stato in grado di farlo utilizzando la visualizzazione galleria. uguale a viewpager in qualsiasi modo. Non so perché la galleria è deprecata
WillingLearner

Questa domanda è stata da allora ampiamente trattata nel [post here] [1] [1]: stackoverflow.com/questions/13914609/…
Ben Pearson,

Sto usando Vierpager con frammenti, quindi posso usare lo stesso approccio?
Asliyanage

Risposte:


206

Per mostrare l'anteprima delle pagine sinistra e destra, impostare i seguenti due valori

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

Se hai bisogno di spazio tra due pagine nel viewpager, aggiungi

viewpager.setPageMargin(int);

2
Sì sono d'accordo con te Jiju Induchoodan .. Per maggiori informazioni si prega di fare riferimento blog.neteril.org/blog/2013/10/14/... e stackoverflow.com/questions/13914609/...~~V~~singular~~3rd
Sripathi

Fantastico, è così semplice :) È possibile ridimensionare le anteprime sulle dimensioni destra e sinistra quando si passa da una pagina all'altra del cercapersone di visualizzazione? Ad esempio, se il frammento è fuori fuoco, la sua scala sarà ~ 0,8, ma quando lo trasciniamo al centro, la scala aumenterà a 1 e il frammento precedente dalla vista centrale cambierà la scala a 0,8 quando esci dallo schermo?
iamthevoid

Funziona! Ma quando provo a ingrandire il layout centrale, viene ingrandito in alto e in basso. La sinistra e la destra non sono visibili a causa dell'imbottitura. Si prega di vedere la domanda stackoverflow.com/questions/52710076/...
Anooj Krishnan G

non funziona con viewpager 2
hamiid reza Gholami

73

La risposta di @JijuInduchoodan è perfetta e funzionante. Tuttavia, poiché sono relativamente nuovo su Android, mi ci è voluto un po 'per capirlo e impostarlo correttamente. Quindi, sto postando questa risposta per riferimento futuro e aiuto chiunque altro sia nei miei stessi panni.

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

Non è necessario impostare alcuna larghezza per la ViewPager'spagina nell'adattatore. Non è richiesto alcun codice aggiuntivo per vedere la pagina precedente e successiva in ViewPager. Tuttavia, se si desidera aggiungere uno spazio vuoto nella parte superiore e inferiore di ciascuna pagina, è possibile impostare il seguente codice sul ViewPager'slayout padre della pagina figlio.

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

Final ViewPager

Questo sarà l'aspetto finale del ViewPager.


62

Soluzione con il nuovo ViewPager2

Al giorno d'oggi dovresti considerare l'utilizzo di ViewPager2 che "sostituisce ViewPager, affrontando la maggior parte dei punti deboli del suo predecessore" :

  • Basato su RecyclerView
  • Supporto layout RTL (da destra a sinistra)
  • Supporto per l'orientamento verticale
  • Supporto affidabile per i frammenti (inclusa la gestione delle modifiche alla raccolta di frammenti sottostante)
  • Animazioni di modifica del set di dati (incluso il DiffUtilsupporto)

Il risultato

inserisci qui la descrizione dell'immagine

Il codice

Nella tua attività / frammento, configura 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)

Aggiungi il HorizontalMarginItemDecoration, che è banale 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
    }

}

Aggiungi le dimensioni che controllano quanto è visibile l'elemento precedente / successivo e il margine orizzontale dell'elemento corrente:

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

inserisci qui la descrizione dell'immagine

Infine aggiungi ViewPager2al tuo layout:

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

Una cosa importante: un ViewPager2elemento deve avere layout_height="match_parent"(altrimenti genera un'eccezione IllegalStateException), quindi dovresti fare qualcosa come:

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

Esempi di PageTransformer

Google ha aggiunto una guida su ViewPager2 che ha 2 PageTransformerimplementazioni che puoi utilizzare come ispirazione: https://developer.android.com/training/animation/screen-slide-2

Informazioni sul nuovo ViewPager2


Stesso problema sui dispositivi oreo, il riempimento iniziale e finale funziona come previsto su altri dispositivi ma oreo dopo ViewPager2. PageTransformer ha risolto il problema, le imbottiture sono sempre le stesse e ho dovuto aggiungereviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr

Devo spostare leggermente la pagina del cercapersone per ottenere questo effetto
Muhammad Saqib

non importa, ho dimenticato di aggiungere questa riga setOffscreenPageLimit(1):)
Muhammad Saqib

Questa è la migliore soluzione che abbia mai trovato. Funziona perfettamente ma sì, NON DIMENTICARE di impostare la larghezza e l'altezza dell'elemento di ViewPager2 su MATCH_PARENT.
khushbu

26

Nel 2017 tale comportamento può essere facilmente ottenuto utilizzando RecyclerViewcon PagerSnapHelper (aggiunto nella versione 25.1.0 della libreria di supporto v7): 

inserisci qui la descrizione dell'immagine

Qualche tempo fa avevo bisogno di questa funzionalità simile a viewpager e ho preparato una piccola libreria:

MetalRecyclerPagerView : qui puoi trovare tutto il codice insieme agli esempi.

Principalmente consiste in un singolo file di classe: MetalRecyclerViewPager.java (e due xml: attrs.xml e ids.xml ).

Spero che aiuti qualcuno e farà risparmiare alcune ore :)


Fuori tema, perché a volte è necessario solo il cercapersone ma bello sapere! Grazie per la condivisione!
sud007

Questo e spettacolare. Avevo già tonnellate di codice di supporto RecyclerView. Basta aggiungere un semplice new PagerSnapHelper().attachToRecyclerView(recyclerView)e ho lo snap della pagina.
Steve il

9

se qualcuno stava ancora cercando una soluzione, avevo personalizzato la ViewPage per ottenerla senza utilizzare il margine negativo, trova un progetto di esempio qui https://github.com/44kksharma/Android-ViewPager-Carousel-UI dovrebbe funzionare nella maggior parte dei casi ma tu può ancora definire il margine della pagina con mPager.setPageMargin(margin in pixel);


7

Puoi farlo nel file xml, usa semplicemente il codice seguente:

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

Per esempio:

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

Nota: se hai bisogno di spazio tra le pagine, imposta padding / margin sui frammenti secondari


3
Ho downvoted. scusa fratello. Questa volta ha funzionato !! Votato di nuovo
shikhar bansal

1

Per coloro che lottano per averlo su schermi diversi,

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

Si noti che quando si imposta nessuno zero padding su un viewpager, il posizionamento degli effetti di bordo del viewpager è incasinato, questo è un bug del viewpager, vedere qui: viewpager bug di edgeeffect

È possibile disabilitare l'effetto bordo impostando android:overScrollMode="never"il viewpager oppure è possibile correggere il bug con una versione leggermente modificata della classe EdgeEffect : correzione ViewPagerEdgeEffect


-10

Usa questo adattatore e classe di frammenti per visualizzare il viewpager nello scroll sinistro e destro. Aggiungi le classi necessarie per scorrere per visualizzare le pagine successive.

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

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.