Android ViewPager - Vorschau der Seite links und rechts anzeigen

107

Ich benutze Android ViewPager. Ich möchte links und rechts eine Vorschau der Seite anzeigen. Ich habe gesehen, wo ich ein Negativ verwenden kann pageMargin, um eine Vorschau der rechten Seite anzuzeigen.

setPageMargin(-100);

Kann ich trotzdem eine Vorschau der linken Seite anzeigen? Es ist im Grunde etwas Ähnliches wie das Galerie-Widget, das ich suche.

Brian Boyle
quelle
Gute Frage! Ich habe kürzlich die Quelle überprüft und glaube, es gibt keinen besseren Weg, wenn Sie den Quellcode nicht ändern möchten. Funktioniert das setPageMargin(-100)richtig?
Macarse
Die GalleryView erledigt die Aufgabe besser, es sei denn, Sie verwenden den ViewPger mit Fragmenten.
Ali AlNoaimi
Ich konnte dies über die Galerieansicht tun. in irgendeiner Weise wie Viewpager.
Ich
Diese Frage wurde seitdem ausführlich in [Beitrag hier] [1] [1] behandelt: stackoverflow.com/questions/13914609/…
Ben Pearson
Ich benutze Vierpager mit Fragmenten. Kann ich den gleichen Ansatz verwenden?
Asliyanage

Antworten:

206

Um die Vorschau der linken und rechten Seite anzuzeigen, stellen Sie die folgenden zwei Werte ein

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

Wenn Sie zwischen zwei Seiten im Viewpager Platz benötigen, fügen Sie hinzu

viewpager.setPageMargin(int);
Jiju Induchoodan
quelle
2
Ja, ich stimme Ihnen zu, Jiju Induchoodan. Weitere Informationen finden Sie unter blog.neteril.org/blog/2013/10/14/… und stackoverflow.com/questions/13914609/…
Sripathi,
Cool, es ist so einfach :) Ist es möglich, die Größe der Vorschau auf der rechten und linken Größe auf den Seiten des Ansichtspagers zu ändern? Wenn beispielsweise das Fragment unscharf ist, beträgt die Skalierung ~ 0,8, aber wenn wir es in die Mitte ziehen, wird die Skalierung auf 1 erhöht, und das vorherige Fragment aus der mittleren Ansicht ändert die Skalierung auf 0,8, wenn der Bildschirm verlassen wird.
iamthevoid
Das funktioniert! Wenn ich jedoch versuche, das mittlere Layout zu zoomen, wird es nach oben und unten gezoomt. Die linke und rechte Seite ist aufgrund der Polsterung nicht sichtbar. Bitte lesen
Anooj Krishnan G
73

Die Antwort von @JijuInduchoodan ist perfekt und funktioniert. Da ich jedoch relativ neu in Android bin, habe ich eine Weile gebraucht, um es richtig zu verstehen und einzustellen. Also poste ich diese Antwort als zukünftige Referenz und helfe allen anderen, die in den gleichen Schuhen wie ich sind.

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

Es ist nicht erforderlich, die Breite der ViewPager'sSeite im Adapter festzulegen. Es ist kein zusätzlicher Code erforderlich, um die vorherige und nächste Seite in anzuzeigen ViewPager. Wenn Sie jedoch oben und unten auf jeder Seite Leerzeichen hinzufügen möchten, können Sie den folgenden Code für ViewPager'sdas übergeordnete Layout der untergeordneten Seite festlegen.

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

Final ViewPager

Dies ist das endgültige Erscheinungsbild des ViewPager.

Rohan Kandwal
quelle
61

Lösung mit dem neuen ViewPager2

Heutzutage sollten Sie in Betracht ziehen, ViewPager2 zu verwenden, das "ViewPager ersetzt und die meisten Schwachstellen seines Vorgängers behebt" :

  • Basierend auf RecyclerView
  • RTL-Layoutunterstützung (von rechts nach links)
  • Unterstützung für vertikale Ausrichtung
  • Zuverlässige Fragmentunterstützung (einschließlich der Bearbeitung von Änderungen an der zugrunde liegenden Fragmentauflistung)
  • Animationen zum Ändern von Datensätzen (einschließlich DiffUtilUnterstützung)

Das Ergebnis

Geben Sie hier die Bildbeschreibung ein

Der Code

Richten Sie in Ihrer Aktivität / Ihrem Fragment den ViewPager2 ein:

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

Fügen Sie das hinzu HorizontalMarginItemDecoration, was trivial ist 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
    }

}

Fügen Sie die Abmessungen hinzu, die steuern, wie viel vom vorherigen / nächsten Element sichtbar ist, und den horizontalen Rand des aktuellen Elements:

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

Geben Sie hier die Bildbeschreibung ein

Fügen Sie schließlich das ViewPager2zu Ihrem Layout hinzu:

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

Eine wichtige Sache: Ein ViewPager2Element muss haben layout_height="match_parent"(andernfalls wird eine IllegalStateException ausgelöst), daher sollten Sie Folgendes tun:

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

Google hat in ViewPager2 eine Anleitung hinzugefügt, die zwei PageTransformerImplementierungen enthält, die Sie als Inspiration verwenden können: https://developer.android.com/training/animation/screen-slide-2

Über den neuen ViewPager2

Albert Vila Calvo
quelle
Das gleiche Problem auf oreo-Geräten, Start und Ende des Auffüllens funktionieren wie erwartet auf anderen Geräten, jedoch oreo nach ViewPager2. PageTransformer hat das Problem behoben, die Auffüllungen sind immer noch gleich und ich musste hinzufügenviewpager.setPageTransformer { page, position -> page.translationX = -1 * position }
zgr
Ich muss die Seite des View Pagers leicht verschieben, um diesen Effekt zu erzielen
Muhammad Saqib
setOffscreenPageLimit(1)
egal
Dies ist die beste Lösung, die ich je gefunden habe. Es funktioniert einwandfrei, aber ja, VERGESSEN SIE NICHT, die Artikelbreite und -höhe von ViewPager2 auf MATCH_PARENT zu setzen.
Khushbu
26

Im Jahr 2017 kann ein solches Verhalten zusätzlich leicht RecyclerViewmit PagerSnapHelper (hinzugefügt in Version 25.1.0 der v7-Unterstützungsbibliothek) erreicht werden: 

Geben Sie hier die Bildbeschreibung ein

Vor einiger Zeit brauchte ich eine solche Viewpager-ähnliche Funktion und bereitete eine winzige Bibliothek vor:

MetalRecyclerPagerView - dort finden Sie den gesamten Code sowie Beispiele.

Hauptsächlich besteht es aus einer einzelnen Klassendatei: MetalRecyclerViewPager.java (und zwei xmls: attrs.xml und ids.xml ).

Hoffe es hilft jemandem und spart einige Stunden :)

Alexander Bilchuk
quelle
Off Topic, weil manchmal nur Pager benötigt wird, aber schön zu wissen! Danke für das Teilen!
Sud007
Das ist fantastisch. Ich hatte bereits Tonnen von RecyclerView-Hilfecode. Einfach ein einfaches hinzufügen new PagerSnapHelper().attachToRecyclerView(recyclerView)und ich habe Seitenschnappschuss.
Steve
9

Wenn jemand noch nach einer Lösung sucht, habe ich die ViewPage so angepasst, dass sie ohne negative Marge erreicht wird. Ein Beispielprojekt finden Sie hier https://github.com/44kksharma/Android-ViewPager-Carousel-UI. Es sollte in den meisten Fällen funktionieren, aber Sie kann noch Seitenrand mit definieren mPager.setPageMargin(margin in pixel);

44kksharma
quelle
7

Sie können dies in einer XML-Datei tun. Verwenden Sie einfach den folgenden Code:

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

Beispielsweise:

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

Hinweis: Wenn Sie Platz zwischen den Seiten benötigen, setzen Sie das Auffüllen / den Rand auf untergeordnete Fragmente

sma6871
quelle
3
Ich habe abgelehnt. Entschuldigung Bruder. Diesmal hat es funktioniert !! Wieder upvoted
Shikhar Bansal
1

Für diejenigen, die Schwierigkeiten haben, dies auf verschiedenen Bildschirmen zu haben,

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

Beachten Sie, dass beim Festlegen von Nicht-Null-Auffüllungen für einen Viewpager die Edgeeffect-Platzierung des Viewpagers durcheinander gebracht wird. Dies ist ein Fehler des Viewpagers. Siehe hier: Viewpager-Edgeeffect-Fehler

Sie können den Kanteneffekt entweder deaktivieren, indem Sie android:overScrollMode="never"den Viewpager festlegen, oder Sie können den Fehler mit einer leicht geänderten Version der EdgeEffect-Klasse beheben : ViewPagerEdgeEffect-Fix

ssynhtn
quelle
-10

Verwenden Sie diesen Fragmentadapter und diese Klasse, um den Viewpager im linken und rechten Bildlauf anzuzeigen. Fügen Sie die erforderlichen Klassen hinzu, um einen Bildlauf zum Anzeigen der nächsten Seiten durchzuführen.

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
quelle