ViewPager mit vorherigen und nächsten Seitengrenzen


144

Ich entwerfe eine Ansicht mit mehreren Seiten. Ich möchte, dass die Kanten der vorherigen und nächsten Seiten wie unten angezeigt werden, und implementiere einen 2-Finger-Wisch, um zwischen den Seiten zu wechseln.

Geben Sie hier die Bildbeschreibung ein

Ich habe versucht, ViewPagermit negativem Seitenrand zu verwenden, wie hier vorgeschlagen aber das zeigt nur eine der Kanten auf dem Bildschirm, nicht beide gleichzeitig.

Alternativ gibt es eine Möglichkeit, einen Teil meiner Ansicht außerhalb des Bildschirms zu positionieren und ihn dann zu animieren, indem ich ihm eine gebe ViewPager Typ Wirkung.

Wie soll ich vorgehen? Vielen Dank !


"Zeigt nur eine der Kanten auf dem Bildschirm, nicht beide gleichzeitig." Sind Sie auf Seite 0 und sehen nur einen Teil von Seite 1? Möglicherweise müssen Sie beispielsweise einen kreisförmigen Pager verwenden und dann Ihre Seite immer auf die "mittlere" Position setzen. Siehe diesen Beitrag und den Kommentar: stackoverflow.com/a/8304474/1851478
logray

Antworten:


100

Ich zitiere mich aus einem Blog-Beitrag zu diesem Thema :

Der dritte Ansatz stammt von Dave Smith, Co-Autor des angesehenen Buches Android Recipes. Er ging in eine ganz andere Richtung und benutzte einen benutzerdefinierten Container, in dem das Ausschneiden von Kindern deaktiviert wurde, um mehr als eine Seite gleichzeitig anzuzeigen.

Sein veröffentlichter Beispielcode zeigt das Ganze in Aktion. Sein container ( com.example.pagercontainer.PagerContainer) umschließt das ViewPagerund ruft setClipChildren(false);sich selbst auf. Obwohl das ViewPagerauf eine ausgewählte Seite fokussiert ist, sind andere Seiten mit Koordinaten außerhalb der ViewPagerGrenzen weiterhin sichtbar, solange sie in das passen PagerContainer. Wenn Sie die Größe ViewPagerkleiner als die Größe festlegen PagerContainer, ViewPagerkönnen die Seiten der Dose auf diese Größe angepasst werden, sodass Platz für andere Seiten bleibt. PagerContainermuss jedoch ein wenig bei Berührungsereignissen helfen, da ViewPagerSwipe-Ereignisse nur an ihren eigenen sichtbaren Grenzen behandelt werden und alle Seiten ignoriert werden, die für die Seiten sichtbar sind.

Geben Sie hier die Bildbeschreibung ein


1
Auf diese Weise kann ich einen Teil der vorherigen und nächsten Seite anzeigen, wie im obigen Bild gezeigt, aber jetzt möchte ich keine scharfen Kanten auf Bildern anzeigen. Ich möchte, dass sie in Richtung Kanten verschwimmen. Bitte leiten Sie mich, wie dies möglich ist Ich benutze Z-Index, um das gleiche zu erreichen
Shruti

2
@ Shruti - fügen Sie einfach ein Überlagerungsbild mit dem gewünschten Effekt hinzu
Daniel L.

2
Ich mache das gleiche, aber es deaktiviert den Over-Scroll-Effekt für das letzte Element. Irgendwelche Hinweise dazu?
Swayam

1
@ CommonsWare: Sir, ich habe Ihre Lösung ausprobiert! Es hat ziemlich gut funktioniert. Der Overscroll ist da. Das einzige Problem ist jetzt, dass die nächste Karte angezeigt wird, aber nicht die vorherige Karte. Das heißt, wenn ich auf Seite 2 bin, kann ich sehen, dass Seite 3 herausschaut, aber nicht Seite 1. Wo könnte ich falsch liegen?
Swayam

2
@ Swayam: Ich habe keine Ahnung.
CommonsWare

110

Ich habe eine ähnliche Lösung:

Stellen Sie am Viewpager die linke und rechte Polsterung ein, z. B. 20dp. Stellen Sie auch den Seitenrand am Viewpager ein, z. B. die Hälfte des Pager-Auffüllens. Vergessen Sie nicht, das Auffüllen der Clips zu deaktivieren.

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

2
Gute Lösung zur Verfügung gestellt.
Akash89

einfachster und bester Weg
HannahCarney

Dies ist das Biest Ja Biest Antwort für die Benennung von Werten xd
silentsudo

1
Randnotiz: Dies funktioniert nicht mit einem benutzerdefinierten Ansicht Pager-Transformator
Voytez

@voytez irgendeine Lösung für Transformator?
Alex

76
  1. Stellen Sie die linke und rechte Polsterung für die Ansicht des gesamten Elements ein. Beispiel 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. Stellen Sie dann den negativen Seitenrand PageViewauf 2 * ein (vorheriges Auffüllen der Ansicht).

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
  3. Optional. Stellen Sie für das erste Element eine linke Auffüllung von Null und für das letzte Element eine rechte Auffüllung von Null ein, um leere Kanten auszublenden. Sie können dies in der Klasse PageAdapteroder Pagefragment tun .


@Sergey, ich kann das mit Ihrer Lösung nicht zum Laufen bringen. Können Sie ein Beispiel posten? thx
Marckaraujo

12
Nur eine Notiz hinzufügen: Bei dieser Lösung befindet sich die Seite 3 beim Verschieben von Seite 1 nach Seite 2 nicht im Speicher, sodass sie verzögert angezeigt wird. Um dies zu beheben, fügen Sie einfach hinzu - yourViewPager.setOffscreenPageLimit (2);
José Barbosa

Ich mache das gleiche, aber es deaktiviert den Over-Scroll-Effekt für das letzte Element. Irgendwelche Hinweise dazu?
Swayam

Ich kann auch nicht scheinen, dass dies funktioniert ... die Ränder scheinen zufällig angezeigt zu werden, wenn ich Bilder mit Skalierung verwende, die auf die Mitte des Zuschnitts eingestellt sind. Hat jemand ein funktionierendes Codebeispiel, das er teilen kann?
Kenyee

2
Wie berühre ich den ersten und letzten Gegenstand? Durch Überprüfen des Seitenindex in OnPageListener?
Hardik9850

47

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

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

Wenn Sie Platz zwischen zwei Seiten im Viewpager benötigen, fügen Sie viewpager.setPageMargin (int) hinzu.

Android ViewPager - Vorschau der Seite links und rechts anzeigen


3
Dies sollte die richtige Antwort sein. Ich denke, dass dies in früheren Versionen von Viewpager möglicherweise nicht funktioniert hat, aber es funktioniert jetzt.
Greg Ennis

Der gleiche Rand wird auch auf der linken Seite der ersten und rechten Seite der letzten Seite hinzugefügt. Irgendwelche Korrekturen
Umesh Aawte

1
Kurze und klarere Antwort.
Imran Ahmed


1

Laden Sie den Quellcode von hier herunter ( ViewPager mit vorherigen und nächsten Seitengrenzen )

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
Dieser Code funktioniert nicht richtig, seine linke Seite ist etwas größer als die rechte Seite
Chirag Joshi

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.