Cómo realizar una actividad de presentación animada en Android con ViewPager
- Andrés Cruz
Las vistas de presentación son un elemento fundamental en cualquier aplicación hoy en día y sobre todo en las aplicaciones móviles en Android ya es una característica común que al momento de instalar la aplicación está presente un sencillo carrusel con sus características viñetas en las cuales se señalan su uso, características, etc y en esta entrada explicaremos como crear una presentación en Android con algunas animaciones empleando el ViewPager el cual es un componente fundamental que ya hemos explicado anteriormente.
Layout: Definiendo la interfaz de nuestro vista de presentación
La vista incluye un par de imágenes que iremos mostrando/ocultando mediante una sencilla animación y esta NO formará parte del ViewPager pero si se irá actualizando dependiendo de la posición en la que se encuentre nuestro carrusel con las imágenes correspondientes:
<FrameLayout
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="88dp">
<ImageView
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:id="@+id/icon_image1"
android:src="@drawable/intro1"/>
<ImageView
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:id="@+id/icon_image2"/>
</FrameLayout>
Definiremos el ViewPager que nos permite crear el típico carrusel con el contenido (texto en este experimento) que se irá mostrando según el desplazamiento lateral (swipe) del usuario:
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/intro_view_pager"/>
Por último definiremos las viñetas que se irán actualizando según la posición del ViewPager:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bottom_pages"
android:orientation="horizontal"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="26dp">
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
<FrameLayout
android:layout_width="5dp"
android:layout_height="5dp"
android:background="#bbbbbb"
android:layout_marginLeft="7dp"/>
</LinearLayout>
Código Java: armando nuestra vista de presentación y animarla
Finalmente llegamos a la parte crucial y es como empleamos la vista anterior para realizar la presentación animada; primero definiremos los textos, imágenes y títulos de nuestra presentación:
icons = new int[]{
R.drawable.intro1,
R.drawable.intro2,
R.drawable.intro3,
R.drawable.intro4,
R.drawable.intro5,
R.drawable.intro6,
R.drawable.intro7
};
titles = new int[]{
R.string.Page1Title,
R.string.Page2Title,
R.string.Page3Title,
R.string.Page4Title,
R.string.Page5Title,
R.string.Page6Title,
R.string.Page7Title
};
messages = new int[]{
R.string.Page1Message,
R.string.Page2Message,
R.string.Page3Message,
R.string.Page4Message,
R.string.Page5Message,
R.string.Page6Message,
R.string.Page7Message
};
Las imágenes y otros elementos:
topImage1 = (ImageView) findViewById(R.id.icon_image1);
topImage2 = (ImageView) findViewById(R.id.icon_image2);
bottomPages = (ViewGroup) findViewById(R.id.bottom_pages);
Ahora establecemos el evento escuchador del ViewPager que se activará cada vez que se realice un swipe en el ViewPager y validamos que no se esté arrastrando y se encuentre en su posición final:
@Override
public void onPageScrollStateChanged(int i) {
// la vista no esta siendo arrastrada || La pagina esta en su posicion final
if (i == ViewPager.SCROLL_STATE_IDLE || i == ViewPager.SCROLL_STATE_SETTLING) {
if (lastPage != viewPager.getCurrentItem()) {
lastPage = viewPager.getCurrentItem();
// oculta/muestra una imagen
final ImageView fadeoutImage;
final ImageView fadeinImage;
if (topImage1.getVisibility() == View.VISIBLE) {
fadeoutImage = topImage1;
fadeinImage = topImage2;
} else {
fadeoutImage = topImage2;
fadeinImage = topImage1;
}
fadeinImage.bringToFront();
fadeinImage.setImageResource(icons[lastPage]);
fadeinImage.clearAnimation();
fadeoutImage.clearAnimation();
Animation outAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.icon_anim_fade_out);
outAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
fadeoutImage.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
Animation inAnimation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.icon_anim_fade_in);
inAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
fadeinImage.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
fadeoutImage.startAnimation(outAnimation);
fadeinImage.startAnimation(inAnimation);
}
}
}
});
}
También aquí se realizan otras funcionalidades como ocultar mostrar la imagen en la cabecera que como indicamos al inicio no forman parte de ViewPager pero si se actualizan conforme el usuario va desplazándose mediante el ViewPager de presentación; las imágenes van ocultándose/mostrandose una por vez y esto se debe para mostrar una sencilla animación al momento de realizar la transición de una imagen a otra; dichas animaciones están definidas incluyendo sus eventos escuchadores e invocadas desde el mismo evento escuchador del ViewPager.
Adaptador del ViewPager para saber la posición de ViewPager en la actividad
Por último definimos un Adapter para nuestro ViewPager el cual nos permitirá colorear las viñetas según la posición en la que nos encontremos y de incrustar (en Android el término se conoce como "inflar") la vista de presentación en nuestro ViewPager:
private class IntroAdapter extends PagerAdapter {
@Override
public int getCount() {
return 7;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = View.inflate(container.getContext(), R.layout.intro_view_layout, NULL);
TextView headerTextView = (TextView) view.findViewById(R.id.header_text);
TextView messageTextView = (TextView) view.findViewById(R.id.message_text);
container.addView(view, 0);
headerTextView.setText(getString(titles[position]));
messageTextView.setText(getString(messages[position]));
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
int count = bottomPages.getChildCount();
for (int a = 0; a < count; a++) {
View child = bottomPages.getChildAt(a);
if (a == position) {
child.setBackgroundColor(0xff2ca5e0);
} else {
child.setBackgroundColor(0xffbbbbbb);
}
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public Parcelable saveState() {
return NULL;
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
if (observer != NULL) {
super.unregisterDataSetObserver(observer);
}
}
}
Y esto es todo, con el código anterior podemos tener un fantástica vista de presentación para nuestra aplicación Android bastante modular y personalizable según necesidades la cual la podemos llevar incluso a convertir en una galería de imágenes como veremos en otra ocasión; el código anterior fue obtenido del recurso que corresponde al Telegram.
Puedes descargar el fuente de este experimento al principio y final de esta entrada:
Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter