2012-08-27 23 views
6

quisiera poner en práctica un ViewPager que utiliza fragmentos y se pueden limpió en un movimiento curcular por ejemplo Página (A < -> B < -> C < -> A). He leído un par de publicaciones sobre cómo se hace esto, p. devolviendo un recuento falso de cuántos elementos hay y estableciendo la posición al comienzo en el medio. how to create circular viewpager?ViewPager Circular que utiliza FragmentPagerAdapter

Todos estos parecen estar basados ​​en un PagerAdapter. Cuando trato de hacer algo similar mientras extiendo FragmentPagerAdapter, tan pronto como devuelvo una FakeCount de páginas obtengo una excepción cuando paso por mis Fragments, solo tengo 2 Fragments. Excepción: java.lang.IllegalStateException: no se puede cambiar la etiqueta del fragmento.

creo que esto se debe a que el FragmentManager cree que estoy en la posición 2, pero la posición 2 puntos al fragmento en la posición 0. ¿Alguien sabe cómo puedo evitar esto? Estoy pensando que debería experimentar extendiendo Fragmentmanager. Cualquier ejemplo o ayuda con esto sería muy apreciado.

+0

he implementado una solución para esto. Casi estoy terminando las pruebas y responderé aquí cuando termine. –

+0

@FernandoCamargo has solucionado esto ?? –

+0

Sí. Lo siento, olvidé responderlo aquí. Voy a publicar la respuesta ahora. –

Respuesta

1

Tengo un proyecto en el GitHub con algunos widgets que he creado. Aquí su:

https://github.com/CyberEagle/AndroidWidgets

En el siguiente paquete, están los adaptadores para ser utilizados con el CircularViewPager: https://github.com/CyberEagle/AndroidWidgets/tree/master/src/main/java/br/com/cybereagle/androidwidgets/adapter

En primer lugar, que va a utilizar en lugar de CircularViewPager ViewPager en su diseño. El CircularViewPager está aquí: https://github.com/CyberEagle/AndroidWidgets/blob/master/src/main/java/br/com/cybereagle/androidwidgets/view/CircularViewPager.java

Este ViewPager espera un WrapperCircularPagerAdapter, en lugar de un PagerAdapter. Este contenedor se utiliza para engañar a ViewPager, lo que hace pensar que hay muchos elementos en ViewPager, pero en realidad repite tus elementos para hacer el efecto circular. Así, en lugar de implementar ya sea PagerAdapter, FragmentPagerAdapter o FragmentStatePagerAdapter, llevarlo a la práctica ya sea CircularFragmentPagerAdapter, CircularFragmentStatePagerAdapter o CircularPagerAdapter. Luego, ajustará su adaptador con WrapperCircularPagerAdapter y configurará el contenedor en CircularViewPager, en lugar de su adaptador. Además, cuando sea el momento de notificar el cambio en el conjunto de datos, llamará a notifyDatasetChanged() en el contenedor.

Al implementar uno de los adaptadores circulares, se dará cuenta de que en lugar de implementar instaseaElement, tendrá que implementar instantiateVirtualItem. Para el adaptador de buscapersonas del fragmento, implementará getVirtualItem en lugar de getItem. Eso es porque he creado el concepto de elementos virtuales.

Para que quede claro, imagínese una vista localizador con 4 elementos, dando que cada elemento representa un musical. Cuando vaya todo el camino hacia la izquierda, verá el cuarto elemento a la izquierda del primero. En realidad, es un elemento completamente nuevo, pero está vinculado al elemento virtual que representa la cuarta música.

Otro ejemplo: imagine que ahora solo hay una música. Verá la misma música a la izquierda y a la derecha. Hay 3 elementos a la vez, pero solo un elemento virtual.

Por lo tanto, como se explicó, el Contenedor está engañando al ViewPager, lo que hace pensar que hay muchos elementos. Para que sea más difícil para el usuario llegar a uno de los extremos de ViewPager (de todos modos, llevaría mucho tiempo), cada vez que ocurre un cambio en el conjunto de datos, ViewPager va al mismo elemento virtual, pero a uno de los artículos reales cerca del medio.

Una cosa más importante es que el CircularViewPager tiene el método setCurrentVirtualItem.Este método calcula qué elemento real es el artículo virtual deseado más cercano y luego usa setCurrentItem para establecerlo. También tiene la opción de usar getCurrentVirtualItem, que devolverá el índice del elemento virtual actual. Tenga en cuenta que si usa getCurrentItem, obtendrá un índice grande.

Bueno, esto es todo. Lo siento por la falta de documentación del proyecto. Estoy planeando documentarlo pronto. También estoy planeando eliminar la necesidad del envoltorio. Siéntase libre de copiar el código (respetando la licencia de Apache 2.0), para tenedor o incluso contribuir a ello.

+0

Implementé el Buscapersonas como lo mencionó. Y estoy usando nuestras clases CircularViewPager, WrapperCircularPagerAdapter y CircularFragmentPagerAdapter como mencionamos anteriormente. Pero sigue obteniendo la excepción: Excepción: java.lang.IllegalStateException: No se puede cambiar la etiqueta del fragmento. Alguna sugerencia ? –

+0

Si agrego 4 fragmentos, entonces mi código funciona bien. Pero mis requisitos son usar solo 2 fragmentos que causen la excepción mencionada anteriormente –

+0

@MiaNKhaLiD, es extraño. Funcionó para mí incluso con solo un fragmento. ¿Podrías mostrarme cómo lo estás usando? –

3

Sé que es un poco tarde, pero esta es la forma en que trabajó para mí:

que necesitaba un golpe circular entre los 3 fragmentos, así que hice los 3 y dos más virtual que me ayude a poner en práctica el bucle página:

public static class FirstViewFragment extends Fragment { 
    // Empty Constructor 
    public FirstViewFragment() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_landing_1, container, false); 
    } 
} 

public static class SecondViewFragment extends Fragment { 
    // Empty Constructor 
    public SecondViewFragment() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_landing_2, container, false); 
    } 
} 

public static class ThirdViewFragment extends Fragment { 
    // Empty Constructor 
    public ThirdViewFragment() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_landing_3, container, false); 
    } 
} 

y dos más fragmentos virtuales que me permitieron pase a la izquierda de la primera y la derecha de la anterior. Los primeros se infla virtuales de la misma presentación que el último actual y el último virtual de la misma disposición que la primera real:

public static class StartVirtualFragment extends Fragment { 
    public StartVirtualFragment() {} 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_landing_3, container, false); 
    } 
} 

public static class EndVirtualFragment extends Fragment { 
    public EndVirtualFragment() {} 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_landing_1, container, false); 
    } 
} 

Mi adaptador:

private class ViewPagerAdapter extends FragmentPagerAdapter { 

    public ViewPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int i) { 
     switch (i) { 
      case 0: 
       return new StartVirtualFragment(); 
      case 1: 
       if (firstViewFragment == null) { 
        firstViewFragment = new FirstViewFragment(); 
       } 
       return firstViewFragment; 
      case 2: 
       if (secondViewFragment == null) { 
        secondViewFragment = new SecondViewFragment(); 
       } 
       return secondViewFragment; 
      case 3: 
       if (thirdViewFragment == null) { 
        thirdViewFragment = new ThirdViewFragment(); 
       } 
       return thirdViewFragment; 
      case 4: 
       return new EndVirtualFragment(); 
     } 
     return null; 
    } 

    @Override 
    public int getCount() { 
     return 5; 
    } 
} 

Y mi página oyente he utilizado la onPageScrollStateChanged para establecer la página correcta e implementar el bucle:

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
     } 

     @Override 
     public void onPageSelected(int position) { 
     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 
      if (state == ViewPager.SCROLL_STATE_DRAGGING) { 
       int pageCount = viewPager.getChildCount(); 
       int currentItem = viewPager.getCurrentItem(); 
       if (currentItem == 0) { 
        viewPager.setCurrentItem(pageCount - 2, false); 
       } else if (currentItem == pageCount - 1) { 
        viewPager.setCurrentItem(1, false); 
       } 
      } 
     } 
    }); 

y al final:

viewPager.setCurrentItem(1); 

Espero ayudado

-2
**If you want to make 3 views visible at same time and make it circular** 

    public abstract class CircularPagerAdapter extends PagerAdapter{ 
     private int count; 
     int[] pagePositionArray; 
     public static final int EXTRA_ITEM_EACH_SIDE = 2; 
     private ViewPager.OnPageChangeListener pageChangeListener; 
     private ViewPager viewPager; 

     public CircularPagerAdapter(final ViewPager pager, int originalCount) { 
      super(); 
      this.viewPager = pager; 
      count = originalCount + 2*EXTRA_ITEM_EACH_SIDE; 
      pager.setOffscreenPageLimit(count-2); 
      pagePositionArray = new int[count]; 
      for (int i = 0; i < originalCount; i++) { 
       pagePositionArray[i + EXTRA_ITEM_EACH_SIDE] = i; 
      } 
      pagePositionArray[0] = originalCount - 2; 
      pagePositionArray[1] = originalCount -1; 
      pagePositionArray[count - 2] = 0; 
      pagePositionArray[count - 1] = 1; 

      pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 

       public void onPageSelected(final int position) { 
        if(pageChangeListener != null) 
        { 
         pageChangeListener.onPageSelected(pagePositionArray[position]); 
        } 

        pager.post(new Runnable() { 
         @Override 
         public void run() { 
          if (position == 1){ 
           pager.setCurrentItem(count-3,false); 
          } else if (position == count-2){ 
           pager.setCurrentItem(2,false); 
          } 
         } 
        }); 
       } 

       public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
        if(pageChangeListener != null) 
        { 
         pageChangeListener.onPageScrolled(pagePositionArray[position],positionOffset,positionOffsetPixels); 
        } 
       } 

       public void onPageScrollStateChanged(int state) { 
        if(pageChangeListener != null) 
        { 
         pageChangeListener.onPageScrollStateChanged(state); 
        } 
       } 
      }); 
     } 


     @Override 
     public int getCount() { 
      return count; 
     } 

     @Override 
     public boolean isViewFromObject(View view, Object object) { 
      return false; 
     } 

     public abstract Object customInstantiateItem(ViewGroup container, int position); 

     public void setPageChangeListener(ViewPager.OnPageChangeListener pageChangeListener) 
     { 
      this.pageChangeListener = pageChangeListener; 
     } 

     @Override 
     public Object instantiateItem(ViewGroup container, int position) { 
      int pageId = pagePositionArray[position]; 
      return customInstantiateItem(container,pageId); 
     } 

     @Override 
     public void destroyItem(View container, int position, Object object) { 
      ((ViewPager) container).removeView((View) object); 
     } 

     public void setFirstItem() 
     { 
      viewPager.setCurrentItem(EXTRA_ITEM_EACH_SIDE - 1); 
     } 
    } 
Cuestiones relacionadas