Android
ViewPager
Buscar..
Introducción
ViewPager es un administrador de diseño que permite al usuario voltear hacia la izquierda y hacia la derecha a través de las páginas de datos. Se usa con más frecuencia junto con Fragmento, que es una forma conveniente de suministrar y administrar el ciclo de vida de cada página.
Observaciones
Una cosa importante a tener en cuenta sobre el uso de ViewPager es que hay dos versiones diferentes de FragmentPagerAdapter
y FragmentStatePagerAdapter
.
Si usa android.app.Fragment
Fragmentos nativos con FragmentPagerAdapter o FragmentStatePagerAdapter, debe usar las versiones de la biblioteca de soporte del adaptador v13, es decir, android.support.v13.app.FragmentStatePagerAdapter
.
Si está utilizando android.support.v4.app.Fragment
support library Fragments con un FragmentPagerAdapter o FragmentStatePagerAdapter, debe usar las versiones de la biblioteca de soporte v4 del adaptador, es decir, android.support.v4.app.FragmentStatePagerAdapter
.
Uso básico de ViewPager con fragmentos.
Un ViewPager
permite mostrar múltiples fragmentos en una actividad que se puede navegar girando hacia la izquierda o hacia la derecha. Un ViewPager
debe ser alimentado de Vistas o Fragmentos usando un PagerAdapter
.
Sin embargo, existen otras dos implementaciones específicas que le resultarán más útiles en caso de utilizar Fragments que son FragmentPagerAdapter
y FragmentStatePagerAdapter
. Cuando se debe crear una instancia de un Fragmento por primera vez, se getItem(position)
para cada posición que se necesite instanciar. El método getCount()
devolverá el número total de páginas para que ViewPager
sepa cuántos Fragmentos deben mostrarse.
Tanto FragmentPagerAdapter
como FragmentStatePagerAdapter
mantienen un caché de los fragmentos que el ViewPager
deberá mostrar. Por defecto, el ViewPager
intentará almacenar un máximo de 3 Fragmentos que corresponden al Fragmento actualmente visible, y los que están al lado de la derecha y la izquierda. Además, FragmentStatePagerAdapter
mantendrá el estado de cada uno de sus fragmentos.
Tenga en cuenta que ambas implementaciones asumen que sus fragmentos mantendrán sus posiciones, por lo que si mantiene una lista de los fragmentos en lugar de tener un número estático de ellos, como puede ver en el método getItem()
, deberá crear una subclase de PagerAdapter
y anular al menos los métodos instantiateItem()
, destroyItem()
y getItemPosition()
.
Solo agregue un ViewPager en su diseño como se describe en el ejemplo básico :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager">
</android.support.v4.view.ViewPager>
</LinearLayout>
Luego, defina el adaptador que determinará cuántas páginas existen y qué fragmento mostrar para cada página del adaptador.
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
//Apply the Adapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
}
}
Si está utilizando android.app.Fragment
, debe agregar esta dependencia:
compile 'com.android.support:support-v13:25.3.1'
Si está utilizando android.support.v4.app.Fragment
, debe agregar esta dependencia:
compile 'com.android.support:support-fragment:25.3.1'
ViewPager con TabLayout
Se puede utilizar un TabLayout
para una navegación más fácil.
Puede configurar las pestañas para cada fragmento en su adaptador usando el método TabLayout.newTab()
pero hay otro método más conveniente y más fácil para esta tarea que es TabLayout.setupWithViewPager()
.
Este método se sincronizará creando y eliminando pestañas de acuerdo con el contenido del adaptador asociado con su ViewPager
cada vez que lo llame.
Además, establecerá una devolución de llamada por lo que cada vez que el usuario pase la página, se seleccionará la pestaña correspondiente.
Solo define un diseño
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabMode="scrollable" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
Luego implemente el FragmentPagerAdapter
y aplíquelo al ViewPager
:
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
private TabLayout mTabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
// Get the ViewPager and apply the PagerAdapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
// link the tabLayout and the viewpager together
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mTabLayout.setupWithViewPager(mViewPager);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Will be displayed as the tab's label
@Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "Fragment 1 title";
case 1:
return "Fragment 2 title";
case 2:
return "Fragment 3 title";
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
}
}
ViewPager con PreferenceFragment
Hasta hace poco, el uso de android.support.v4.app.FragmentPagerAdapter
impediría el uso de PreferenceFragment
como uno de los fragmentos utilizados en FragmentPagerAdapter.
Las últimas versiones de la biblioteca de soporte v7 ahora incluyen la clase PreferenceFragmentCompat
, que funcionará con un ViewPager y la versión v4 de FragmentPagerAdapter.
Fragmento de ejemplo que extiende PreferenceFragmentCompat
:
import android.os.Bundle;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.view.View;
public class MySettingsPrefFragment extends PreferenceFragmentCompat {
public MySettingsPrefFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_settings_pref);
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
}
}
Ahora puede usar este fragmento en una subclase android.support.v4.app.FragmentPagerAdapter
:
private class PagerAdapterWithSettings extends FragmentPagerAdapter {
public PagerAdapterWithSettings(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
case 2:
return new MySettingsPrefFragment();
default:
return null;
}
}
// .......
}
Agregar un ViewPager
Asegúrese de que la siguiente dependencia se agregue al archivo build.gradle
su aplicación en las dependencias:
compile 'com.android.support:support-core-ui:25.3.0'
Luego agregue el ViewPager
a su diseño de actividad:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Luego define tu PagerAdapter
:
public class MyPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
@Override
public Object instantiateItem(ViewGroup collection, int position) {
// Create the page for the given position. For example:
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.xxxx, collection, false);
collection.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
// Remove a page for the given position. For example:
collection.removeView((View) view);
}
@Override
public int getCount() {
//Return the number of views available.
return numberOfPages;
}
@Override
public boolean isViewFromObject(View view, Object object) {
// Determines whether a page View is associated with a specific key object
// as returned by instantiateItem(ViewGroup, int). For example:
return view == object;
}
}
Finalmente configure el ViewPager
en su actividad:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(this));
}
}
ViewPager con un indicador de puntos
Todo lo que necesitamos es: ViewPager , TabLayout y 2 dibujables para puntos seleccionados y predeterminados.
En primer lugar, debemos agregar TabLayout
a nuestro diseño de pantalla y conectarlo con ViewPager
. Podemos hacer esto de dos maneras:
TabLayout anidado en ViewPager
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
En este caso,
TabLayout
se conectará automáticamente conViewPager
, peroTabLayout
estará al lado deViewPager
, no sobre él.
TabLayout separado
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
En este caso, podemos poner
TabLayout
cualquier lugar, pero tenemos que conectarTabLayout
conViewPager
programáticamente
ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);
Una vez que creamos nuestro diseño, tenemos que preparar nuestros puntos. Entonces creamos tres archivos: selected_dot.xml
, default_dot.xml
y tab_selector.xml
.
selected_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
</layer-list>
default_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
</item>
</layer-list>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_dot"/>
</selector>
Ahora necesitamos agregar solo 3 líneas de código a TabLayout
en nuestro diseño xml y listo.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Configurar OnPageChangeListener
Si necesita escuchar los cambios en la página seleccionada, puede implementar el ViewPager.OnPageChangeListener
escucha ViewPager.OnPageChangeListener
en el ViewPager:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
// This method will be invoked when a new page becomes selected. Animation is not necessarily complete.
@Override
public void onPageSelected(int position) {
// Your code
}
// This method will be invoked when the current page is scrolled, either as part of
// a programmatically initiated smooth scroll or a user initiated touch scroll.
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Your code
}
// Called when the scroll state changes. Useful for discovering when the user begins
// dragging, when the pager is automatically settling to the current page,
// or when it is fully stopped/idle.
@Override
public void onPageScrollStateChanged(int state) {
// Your code
}
});