example ejemplo dev android android-viewpager viewflipper viewanimator

android - ejemplo - ViewPager con límites de página anterior y siguiente



viewflipper android ejemplo (7)

Estoy diseñando una vista con varias páginas. Quiero que los bordes de las páginas anteriores y siguientes se muestren a continuación e implemente un deslizamiento de dos dedos para alternar entre las páginas.

Intenté usar ViewPager con margen de página negativo como se sugiere here pero que solo muestra uno de los bordes en la pantalla, no ambos simultáneamente.

Alternativamente, ¿hay alguna manera en que pueda ViewPager parte de mi vista fuera de la pantalla y luego animarla dándole un efecto de tipo ViewPager ?

¿Cómo debo hacerlo? Gracias !


  1. Ajuste el relleno izquierdo y derecho para ver todo el elemento. Ejemplo 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. A continuación, configure el margen de página negativo para PageView igual a 2 * (relleno de vista anterior)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2, getResources().getDisplayMetrics()); mViewPager.setPageMargin(-margin);

  3. Opcional. Establezca cero para el primer elemento y cero para el último elemento para ocultar los bordes vacíos. Puede hacer esto en la PageAdapter o fragmento de Page .


Citando a mí mismo desde una publicación de blog sobre este tema :

El tercer enfoque proviene de Dave Smith, coautor del reconocido libro Android Recipes. Iba en una dirección muy diferente, utilizando un contenedor personalizado que desactivaba el recorte de niños para mostrar más de una página a la vez.

Su código de muestra publicado muestra todo en acción. Su contenedor ( com.example.pagercontainer.PagerContainer ) envuelve ViewPager y llama a setClipChildren(false); en sí mismo, por lo tanto, aunque ViewPager está enfocado en una página seleccionada, otras páginas que tienen coordenadas más allá de los límites de ViewPager siguen siendo visibles, siempre y cuando quepan dentro del PagerContainer . Al dimensionar el ViewPager para que sea más pequeño que el PagerContainer , el ViewPager puede ViewPager tamaño de sus páginas a ese tamaño, dejando espacio para que se vean otras páginas. PagerContainer embargo, PagerContainer necesita ayudar un poco con los eventos táctiles, ya que ViewPager solo manejará eventos de deslizamiento en sus propios límites visibles, ignorando cualquier página visible a los lados.


Descargue el código fuente desde aquí ( ViewPager con límites de página anterior y siguiente )

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


Hace algún tiempo necesité esa característica y preparé una pequeña biblioteca que usa RecyclerView con PagerSnapHelper (agregado en la versión 25.1.0 de la biblioteca de soporte v7) en lugar de la clásica ViewPager :

MetalRecyclerPagerView : puedes encontrar todo el código junto con ejemplos allí.

Principalmente consiste en un solo archivo de clase: MetalRecyclerViewPager.java (y dos xmls: attrs.xml e ids.xml ).

Espero que ayude a alguien :)



Tengo una solución similar:

En el visor, configure el relleno izquierdo y derecho, por ejemplo, 20dp. También establece el margen de la página en el visor, por ejemplo, la mitad del relleno del buscapersonas. Y no olvide deshabilitar el relleno del clip.

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


si alguien aún está buscando una solución, he personalizado la página de visualización para lograrlo sin usar un margen negativo, encuentre un proyecto de muestra aquí https://github.com/44kksharma/Android-ViewPager-Carousel-UI debería funcionar en la mayoría de los casos, pero usted aún puede definir el margen de la página con mPager.setPageMargin(margin in pixel);