ViewPager com limites de página anterior e seguinte


144

Estou projetando uma exibição com várias páginas. Quero que as bordas das páginas anteriores e seguintes sejam mostradas como abaixo e implemente um furto de dois dedos para alternar entre as páginas.

insira a descrição da imagem aqui

Tentei usar ViewPagercom margem de página negativa, conforme sugerido aqui, mas isso mostra apenas uma das bordas da tela, não as duas simultaneamente.

Como alternativa, existe alguma maneira de posicionar parte da minha visão fora da tela e animá-la, dando-lhe um ViewPagerefeito de tipo.

Como devo fazer isso? Obrigado !


"mostra apenas uma das bordas da tela, não as duas simultaneamente." Você está na página 0 e vê apenas parte da página 1? Talvez você precise usar um pager circular, por exemplo, e depois definir sua página sempre para a posição "intermediária". Veja esta postagem e o comentário: stackoverflow.com/a/8304474/1851478
logray

Respostas:


100

Citando-me de uma postagem de blog sobre este assunto :

A terceira abordagem vem de Dave Smith, co-autor do conceituado livro Android Recipes. Ele foi em uma direção muito diferente, usando um contêiner personalizado que desativava o recorte de crianças para mostrar mais de uma página por vez.

Seu código de amostra publicado mostra tudo em ação. Seu container ( com.example.pagercontainer.PagerContainer) envolve ViewPagere chama setClipChildren(false);a si próprio, portanto, embora o ViewPagerfoco esteja em uma página selecionada, outras páginas que têm coordenadas além dos ViewPagerlimites ainda são visíveis, desde que se encaixem no PagerContainer. Ao dimensionar ViewPagerpara que seja menor que o PagerContainer, a ViewPagerlata pode dimensionar suas páginas para esse tamanho, deixando espaço para outras páginas serem vistas. PagerContainer, no entanto, precisa ajudar um pouco com os eventos de toque, pois ViewPagersó manipulará eventos de furto em seus próprios limites visíveis, ignorando as páginas visíveis para os lados.

insira a descrição da imagem aqui


1
usando isso, sou capaz de mostrar parte da página anterior e da página seguinte, como mostra a imagem acima, mas agora não quero mostrar bordas nítidas nas imagens. i usar z-índice para atingir o mesmo
Shruti

2
@Shruti - basta adicionar uma imagem sobreposta com o efeito desejado
Daniel L.

2
Eu faço o mesmo, mas desativa o efeito de rolagem excessiva para o último item. Alguma pista sobre isso?
Swayam

1
@ CommmonsWare: Senhor, eu tentei sua solução! Funcionou muito bem. A superlotação está lá. O único problema agora é que o próximo cartão é exibido, mas não o anterior. Ou seja, se eu estiver na página 2, posso ver a página 3 aparecendo, mas não a página 1. Onde eu poderia estar errado?
Swayam

2
@Swayam: Não faço ideia.
CommonsWare

110

Eu tenho uma solução semelhante:

No visor, defina o preenchimento esquerdo e direito, por exemplo, 20dp. Defina também a margem da página no visor, por exemplo, metade do preenchimento do pager. E não se esqueça de desativar o preenchimento de clipe.

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

2
Boa solução fornecida.
akash89

mais fácil e melhor maneira
HannahCarney

Esta é a resposta besta fera sim para considerar valores de nomeação xd
silentsudo

1
nota: este não vai funcionar com um transformador de exibição personalizada pager
voytez

@voytez alguma solução para transformador?
Alex

76
  1. Defina o preenchimento esquerdo e direito para a exibição de itens inteiros. Exemplo de 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. Em seguida, defina a margem negativa da página para PageViewigual a 2 * (preenchimento de visualização anterior)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
    
  3. Opcional. Defina zero preenchimento esquerdo para o primeiro item e zero preenchimento direito como último item para ocultar bordas vazias. Você pode fazer isso na classe PageAdapterou Pagefragment.


@ Emery, não posso fazer isso funcionar com sua solução, você poderia postar um exemplo? thx
Marckaraujo

12
basta adicionar uma observação: com esta solução quando você desliza da página 1 para a página 2, a página 3 não está na memória e, portanto, aparece com um atraso. para corrigir isso basta adicionar - yourViewPager.setOffscreenPageLimit (2);
José Barbosa

Eu faço o mesmo, mas desativa o efeito de rolagem excessiva para o último item. Alguma pista sobre isso?
Swayam

Também não consigo fazer com que isso funcione ... as margens parecem ser exibidas aleatoriamente se eu usar imagens com escala definida para cortar o centro. Alguém tem um exemplo de código funcional que pode compartilhar?
Kenyee

2
Como tocar no primeiro e no último item? Verificando o índice da página no OnPageListener?
Hardik9850

47

Para mostrar a visualização das páginas esquerda e direita, defina os dois valores a seguir

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

Se você precisar de espaço entre duas páginas no viewpager, adicione viewpager.setPageMargin (int)

Android ViewPager - Mostrar pré-visualização da página à esquerda e à direita


3
Esta deve ser a resposta correta. Eu acho que talvez isso não funcionou em versões anteriores do viewpager, mas funciona agora.
Greg Ennis

É adicionar a mesma margem no lado esquerdo da primeira e no lado direito da última página. Qualquer correção
Umesh Aawte

1
Resposta curta e mais clara.
Imran Ahmed


1

Faça o download do código fonte aqui ( ViewPager com os limites da página anterior e da próxima )

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
Este código não está funcionando corretamente, a sua página lado esquerdo mostrando pouco maior do que o lado direito
Chirag Joshi

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.