lunes, 4 de marzo de 2013

Ejemplo Con ViewPager Extendido

En esta ocasión vamos a continuar un poco mas con ejemplos de Android. Hace algún tiempo publique un post sobre como utilizar ViewPager en Android y hace algunos días recibí una pregunta de un lector sobre como hacer cosas mas avanzadas en el View Pager. Para recordar un poco aquel ejemplo desplegaba dos vistas similares (el reloj de Android) pero con un color de fondo diferente. Al deslizar la vista hacia la derecha o izquierda el View Pager cambiaba la vista a desplegar en pantalla y se puede observar el cambio en el color de fondo. La pregunta de Oscar Sanchez (gracias por leer el blog) es, como acceder al reloj dentro de cada uno de los fragmentos y realizar operaciones con el ?.

Bueno en Android como en casi todas las plataformas existen varias maneras de hacer las cosas, solo es cuestión de seleccionar la que mas te guste y analizar los pros y contras. Así que para contestar esta pregunta la primera aproximación que utilizaremos sera el manejo interno.  Como ya habíamos visto en nuestro ejemplo anterior habíamos creado un PageAdapter que nos manejaba los diferentes fragmentos que agregábamos en una lista y añadiamos  3 fragmentos iguales pero con diferente color de fondo. Como la documentación de Android lo dice, un fragmento es una poción de una actividad que cuenta con su propio ciclo de vida y espacio para dibujar vistas. Por lo tanto en nuestro fragmento podemos manejar nuestras vistas y eventos internamente. Entonces vamos a extender nuestra clase fragmento para que se vea de esta manera.


public class PlainColorFragment extends Fragment {

int color = Color.GREEN;
View view = null;
AnalogClock clock = null;
public PlainColorFragment(int color){
this.color = color;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.color_layout, null); 
clock = (AnalogClock) view.findViewById(R.id.analogClock1);
clock.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startAnimationOnClock();
}
});
view.setBackgroundColor(this.color);
return view; 
}
public void startAnimationOnClock(){
Animation anim = 
AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
clock.startAnimation(anim);
}
}

Lo que hicimos, es simplemente tener una variable que apunte a nuestro AnalogClock llamada clock y en el evento onCreateView asignar esa variable a la vista analogClock1 que se encuentra dentro de nuestro layout. Y ya con nuestra variable clock le asignamos un evento OnClickListener para que cuando el usuario toque la pantalla una simple animación se ejecute, esto es llamar al método startAnimationOnClock ( vean que el método es publico y visible para otras clases, por que luego lo usaremos para otras cosas). Ahora si, al modificar nuestra aplicación previa de esta manera veremos al tocar el reloj de cualquier fragmento seleccionado la animación se ejecutara. 

Nuestra segunda aproximación, en algunas ocasiones es necesario mandar una señal desde fuera de nuestros fragmentos hacia el interior para ejecutar ciertas instrucciones; como por ejemplo la selección de algún ítem del menú o algún otro evento externo . En esta ocasión, haremos que la animación del reloj del fragmento seleccionado se ejecute cuando se seleccione desde el menú. Lo primero que tendríamos que hacer es saber cual fragmento es el que esta actualmente seleccionado; cual reloj de los varios disponibles tendremos que animar para que el usuario lo vea (no tendría caso animar un reloj que este invisible para el usuario, obvias razones). Por lo tanto crearemos una clase que nos guarde el indice del fragmento que el usuario selecciona. La clase se ve de esta manera:


public class PageChangeListener implements OnPageChangeListener {
int currentIndex = 0;
@Override
public void onPageScrollStateChanged(int arg0) {
//Do Nothing
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
//No Nothing
}
@Override
public void onPageSelected(int arg0) {
currentIndex = arg0;
}
public int getCurrentIndex() {
return currentIndex;
}
}


Hace nada, nomas que guardar el numero de indice de la pagina seleccionada en una variable y exponerla por medio de un getter. Esta clase se va a relacionar con el ViewPager con el método setOnPageChangeListener para que cada vez que se haga un cambio de pagina el indice sea almacenado en nuestra variable currentIndex. Y por ultimo en nuestra actividad principal agregaremos métodos para que cuando el botón del menú sea presionado el fragmento visible sea retraído desde nuestro Adapter y llamar al metodo startAnimationOnClock (es por esto que nuestro método es públicamente visible). Asi que nuestra actividad principal se ve de esta manera: 


public class MainActivity extends FragmentActivity {
ViewPager pager = null;
PageChangeListener pageChangeListener = null;
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        pager = (ViewPager) findViewById(R.id.pager);
        
        MyFragmentPagerAdapter adapter = 
        new MyFragmentPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new PlainColorFragment(Color.RED));
        adapter.addFragment(new PlainColorFragment(Color.GREEN));
        adapter.addFragment(new PlainColorFragment(Color.BLUE));
        pageChangeListener = new PageChangeListener();
        pager.setOnPageChangeListener(pageChangeListener);
        pager.setAdapter(adapter);
    }
        private void startAnimationOnCurrentPage(){
        MyFragmentPagerAdapter adapter =  
         (MyFragmentPagerAdapter) pager.getAdapter();
        PlainColorFragment fragment = 
    (PlainColorFragment) adapter.getItem(pageChangeListener.getCurrentIndex());
        fragment.startAnimationOnClock();
        }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.main_menu_start_anim_current_item:
startAnimationOnCurrentPage();
default:
return super.onOptionsItemSelected(item);
}
}    
}

El método importante en esta actividad es startAnimationOnCurrentPage, ya que dentro de el retraemos nuestro adaptador y utilizamos el indice de nuestro pageChangeListener para así poder obtener el fragmento que esta siendo desplegado al usuario. Una vez que tenemos nuestro fragmento lo único que hacemos es llamar startAnimationOnClock() para que la animación en el reloj sea ejecutada. De esta manera logramos propagar un evento ocurrido en el menú de nuestra actividad hacia dentro de las vistas localizadas dentro de nuestro ViewPager.

En esta ocasión vimos como ejecutar una simple operación de animación en la pagina actual de nuestro ViewPager pero en su lugar podríamos  realizar cualquier otro tipo de operación. Retraer las vistas internas, hacerlas invisibles, eliminarlas, cambiarles colores, fondos, etc. Este pequeño post es simplemente para ejemplificar un poco mas como trabajar con ViewPagers en Android. 

Espero y el ejemplo les sea de utilidad y como siempre, el código fuente esta a su disposición en mi pagina de github https://github.com/ti3r/view_pager_test. Pueden descargar, revisar y utilizar el código a su conveniencia. Si este post les gusto por favor dejen sus comentarios, compartan el blog o escriban un e-mail o comentario con dudas  o recomendaciones para poder mejorar este espacio.

Un Saludo a todos y gracias por leer.













2 comentarios:

  1. Hola, quisiera saber como puedo cambiar el fragmento en el que inicia, es decir, tengo tres fragmentos y no quiero que inicie en el primero de la lista sino en el segundo, quiero saber como se podría hacer eso. Gracias

    ResponderEliminar
    Respuestas
    1. Hola que tal tatiana, puedes cambiar el fragmento que esta seleccionado con el metodo setCurrentItem del ViewPager, con ese metodo seleccionas la pagina actual.
      Espero y te sirva.
      Saludos

      Eliminar