ViewPager con i limiti della pagina precedente e successiva


144

Sto progettando una vista con più pagine. Voglio che i bordi delle pagine precedenti e successive vengano visualizzati come di seguito e implementare un tocco con due dita per passare da una pagina all'altra.

inserisci qui la descrizione dell'immagine

Ho provato a utilizzare ViewPagercon un margine di pagina negativo come suggerito qui ma che mostra solo uno dei bordi sullo schermo, non entrambi contemporaneamente.

In alternativa, c'è un modo per posizionare parte della mia vista fuori dallo schermo e poi animarlo dandogli un ViewPagereffetto di tipo.

Come devo procedere? Grazie !


"mostra solo uno dei bordi sullo schermo, non entrambi contemporaneamente." Sei sulla pagina 0 e vedi solo parte della pagina 1? Forse è necessario utilizzare un cercapersone circolare, ad esempio, e quindi impostare la pagina sempre in posizione "centrale". Vedi questo post e il commento: stackoverflow.com/a/8304474/1851478
logray

Risposte:


100

Citando me stesso da un post sul blog su questo argomento :

Il terzo approccio viene da Dave Smith, coautore del famoso libro Android Recipes. Andò in una direzione molto diversa, usando un contenitore personalizzato che disabilitava il ritaglio dei bambini per mostrare più di una pagina alla volta.

Il suo codice di esempio pubblicato mostra tutto in azione. Il suo contenitore ( com.example.pagercontainer.PagerContainer) racchiude ViewPagere chiama setClipChildren(false);se stesso, quindi anche se ViewPagerè focalizzato su una pagina selezionata, altre pagine che hanno coordinate oltre i ViewPagerlimiti sono ancora visibili, purché rientrino nelPagerContainer . Dimensionando il ViewPagerper essere più piccolo di il PagerContainer, la ViewPagerlattina può ridimensionare le sue pagine a quella dimensione, lasciando spazio per altre pagine da vedere. PagerContainer, tuttavia, deve dare una mano con gli eventi di tocco, poiché ViewPagergestirà gli eventi di scorrimento solo sui propri limiti visibili, ignorando tutte le pagine visibili ai lati.

inserisci qui la descrizione dell'immagine


1
usando questo, sono in grado di mostrare parte della pagina precedente e successiva come mostrato nell'immagine sopra, ma ora non voglio mostrare spigoli vivi sulle immagini. Voglio che sfocino verso i bordi..per favore guidami su come posso uso z-index per ottenere lo stesso risultato
Shruti,

2
@Shruti - basta aggiungere un'immagine di sovrapposizione con l'effetto desiderato
Daniel L.

2
Faccio lo stesso ma disabilita l'effetto di over-scroll per l'ultimo elemento. Qualche indizio su questo?
Swayam,

1
@CommonsWare: Signore, ho provato la tua soluzione! Ha funzionato abbastanza bene. Il overscroll è lì. L'unico problema ora è che la carta successiva mostra, ma non la carta precedente. Cioè, se mi trovo a pagina 2, posso vedere sbirciare pagina 3, ma non pagina 1. Dove avrei potuto andare storto?
Swayam,

2
@Swayam: non ne ho idea.
CommonsWare

110

Ho una soluzione simile:

Nel viewpager impostare l'imbottitura sinistra e destra, ad es. 20dp. Impostare anche il margine della pagina sul viewpager, ad esempio metà del riempimento del pager. E non dimenticare di disabilitare il padding di clip.

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

2
Buona soluzione fornita.
Akash89,

Il modo più semplice e migliore
HannahCarney

Questa è la bestia si bestia risposta per considerare i valori di denominazione xd
silentsudo

1
nota a
margine

@voytez qualche soluzione per trasformatore?
Alex

76
  1. Imposta l'imbottitura sinistra e destra per la visualizzazione dell'intero elemento. Esempio 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. Quindi impostare un margine di pagina negativo per PageViewuguale a 2 * (riempimento della vista precedente)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
  3. Opzionale. Impostare zero imbottitura sinistra per il primo elemento e zero imbottitura destra per l'ultimo elemento per nascondere i bordi vuoti. Puoi farlo nella classe PageAdaptero Pageframmento.


@Sergey, non riesco a far funzionare questo con la tua soluzione, potresti pubblicare un esempio? grazie
Marckaraujo,

12
basta aggiungere una nota: con questa soluzione quando si scorre da pagina 1 a pagina 2, la pagina 3 non è in memoria, quindi verrà visualizzata con un ritardo. per risolvere il problema basta aggiungere - yourViewPager.setOffscreenPageLimit (2);
José Barbosa,

Faccio lo stesso ma disabilita l'effetto di over-scroll per l'ultimo elemento. Qualche indizio su questo?
Swayam,

Nemmeno io riesco a farlo funzionare ... i margini sembrano mostrati casualmente se uso immagini con scala impostata per ritagliare il centro. Qualcuno ha un esempio di codice funzionante che può condividere?
Kenyee,

2
Come toccare il primo e l'ultimo elemento? Controllando l'indice delle pagine in OnPageListener?
Hardik9850,

47

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

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

Se hai bisogno di spazio tra due pagine nel viewpager, aggiungi viewpager.setPageMargin (int)

Android ViewPager - Mostra l'anteprima della pagina a sinistra e a destra


3
Questa dovrebbe essere una risposta corretta. Penso che forse questo non funzionasse nelle versioni precedenti di viewpager ma ora funziona.
Greg Ennis,

Aggiunge lo stesso margine sul lato sinistro del primo e del lato destro dell'ultima pagina. Qualsiasi correzione
Umesh Aawte,

1
Risposta breve e più chiara.
Imran Ahmed,

10

se qualcuno stava ancora cercando una soluzione, avevo personalizzato ViewPage per ottenerlo senza usare il margine negativo, trova qui un progetto di esempio 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);


1

Scarica il codice sorgente da qui ( ViewPager con i limiti della pagina precedente e successiva )

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
Questo codice non funziona correttamente, mostrando la pagina di sinistra un po 'più grande di quella di destra
Chirag Joshi

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.