ViewPager z granicami poprzedniej i następnej strony


144

Projektuję widok z wieloma stronami. Chcę, aby krawędzie poprzednich i następnych stron były wyświetlane jak poniżej i zaimplementuj przesunięcie 2 palcami, aby przełączać się między stronami.

wprowadź opis obrazu tutaj

Próbowałem używać ViewPagerz negatywnym marginesem strony, jak sugerowano tutaj, ale pokazuje to tylko jedną krawędź na ekranie, a nie obie jednocześnie.

Alternatywnie, czy istnieje sposób, w jaki mogę umieścić część widoku poza ekranem, a następnie ożywić go, nadając mu ViewPagerefekt czcionki.

Jak mam się do tego zabrać? Dzięki !


„pokazuje tylko jedną krawędź na ekranie, a nie obie jednocześnie”. Czy jesteś na stronie 0 i widzisz tylko część strony 1? Być może będziesz musiał użyć np. Okrągłego pagera, a następnie ustawiać stronę zawsze w „środkowej” pozycji. Zobacz ten post i komentarz: stackoverflow.com/a/8304474/1851478
logray

Odpowiedzi:


100

Cytując siebie z wpisu na blogu na ten temat :

Trzecie podejście pochodzi od Dave'a Smitha, współautora cenionej książki Android Recipes. Poszedł w zupełnie innym kierunku, używając niestandardowego kontenera, który uniemożliwiał dzieciom wyświetlanie wycinania więcej niż jednej strony na raz.

Jego opublikowany przykładowy kod pokazuje całość w akcji. Jego kontener ( com.example.pagercontainer.PagerContainer) zawija ViewPageri wywołuje setClipChildren(false);siebie, więc nawet jeśli ViewPagerjest skoncentrowany na jednej wybranej stronie, inne strony, które mają współrzędne poza ViewPagergranicami, są nadal widoczne, o ile mieszczą się w PagerContainer. Przez doborze ViewPagerbyć mniejsza niż PagerContainerThe ViewPagerrozmiar może jej strony do tej wielkości, pozostawiając miejsce na innych stronach widać. PagerContainerjednak musi trochę pomóc w przypadku zdarzeń dotykowych, ponieważ ViewPagerobsługuje tylko zdarzenia przesunięcia we własnych widocznych granicach, ignorując wszystkie strony widoczne po bokach.

wprowadź opis obrazu tutaj


1
Używając tego, jestem w stanie pokazać część poprzedniej i następnej strony, jak pokazano na powyższym obrazku, ale teraz nie chcę pokazywać ostrych krawędzi na obrazach, chcę, aby rozmazały się w kierunku krawędzi ... proszę, poprowadź mnie, w jaki sposób Używam indeksu z do osiągnięcia tego samego
Shruti,

2
@Shruti - po prostu dodaj obraz nakładki z efektem, który chcesz
Daniel L.

2
Robię to samo, ale wyłącza efekt przewijania ostatniego elementu. Jakieś wskazówki na ten temat?
Swayam

1
@CommonsWare: Sir, wypróbowałem twoje rozwiązanie! Działało całkiem nieźle. Jest tam przeskok. Jedynym problemem jest teraz to, że wyświetla się następna karta, ale nie poprzednia. To znaczy, jeśli jestem na stronie 2, widzę, jak wygląda strona 3, ale nie strona 1. Gdzie mogłem się pomylić?
Swayam

2
@Swayam: Nie mam pojęcia.
CommonsWare

110

Mam podobne rozwiązanie:

W viewpager ustaw dopełnienie lewe i prawe, np. 20dp. Ustaw również margines strony na stronie podglądu, np. Połowę wypełnienia pagera. I nie zapomnij wyłączyć wypełniania klipów.

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

2
Zapewniono dobre rozwiązanie.
akash89

najłatwiejszy i najlepszy sposób
HannahCarney

To jest bestia, tak, bestia, na którą należy
zwrócić

1
uwaga boczna: to nie zadziała z niestandardowym transformatorem pagera widoku
voytez

@voytez jakieś rozwiązanie dla transformatora?
Alex

76
  1. Ustaw dopełnienie z lewej i prawej strony dla widoku całego elementu. Przykład 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. Następnie ustaw ujemny margines strony na PageViewrówny 2 * (dopełnienie poprzedniego widoku)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
  3. Opcjonalny. Ustaw zero dopełnienia z lewej strony dla pierwszego elementu i zerowe dopełnienie z prawej strony dla ostatniego elementu, aby ukryć puste krawędzie. Możesz to zrobić w klasie PageAdapterlub Pagefragment.


@Sergey, nie mogę tego zrobić z twoim rozwiązaniem, czy możesz opublikować przykład? thx
Marckaraujo

12
po prostu dodawanie notatki: dzięki temu rozwiązaniu podczas przesuwania się ze strony 1 na stronę 2 strona 3 nie jest w pamięci, więc pojawi się z opóźnieniem. aby to naprawić po prostu dodaj - yourViewPager.setOffscreenPageLimit (2);
José Barbosa

Robię to samo, ale wyłącza efekt przewijania ostatniego elementu. Jakieś wskazówki na ten temat?
Swayam

Wydaje się, że to też nie działa ... marginesy wydają się być wyświetlane losowo, jeśli używam obrazów ze skalą ustawioną na środkowe przycięcie. Czy ktoś ma działający przykład kodu, którym może się podzielić?
kenyee

2
Jak dotknąć pierwszej i ostatniej pozycji? Sprawdzając indeks strony w OnPageListener?
Hardik9850

47

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

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

Jeśli potrzebujesz odstępu między dwiema stronami w viewpager, dodaj viewpager.setPageMargin (int)

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


3
To powinna być poprawna odpowiedź. Myślę, że może to nie działało we wcześniejszych wersjach programu Viewpager, ale teraz działa.
Greg Ennis

Dodaje również ten sam margines po lewej stronie pierwszej i prawej strony ostatniej strony. Wszelkie poprawki
Umesh Aawte

1
Krótka i bardziej jasna odpowiedź.
Imran Ahmed


1

Pobierz kod źródłowy stąd ( ViewPager z granicami poprzedniej i następnej strony )

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
Ten kod nie działa poprawnie, jego lewa strona jest nieco większa niż prawa
Chirag Joshi

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.