Vea la traducción al deslizar un ViewPager
Estaba leyendo un ejemplo sobre la personalización de la animación de página deslizante de ViewPager
que implica traducir la página ( View
) a una cierta cantidad. El ejemplo es de los documentos . Específicamente, se trata de una implementación llamada ZoomOutPageTransformer
que se puede establecer en un ViewPager
través de setPageTransformer()
para personalizar cómo se desliza la página (incorporando una animación de zoom en ella).
Así es como se supone que el resultado final es:
- ViewPager onPageSelected para la primera página
- Llamar setHasOptionsMenu (true) de un fragmento da como resultado múltiples llamadas a onCreateOptionsMenu en Activity
- ListFragment no vuelve a mostrar datos al llamar desde FragmentStatePagerAdapter
- Los valores de EditText en Android Fragment no se actualizan
- Listview no actualizar en fragmento con las pestañas viewpager
Ahora, describen cómo lo van a hacer:
En su implementación de
transformPage()
, puede crear animaciones de diapositivas personalizadas determinando qué páginas deben transformarse en función de la posición de la página en la pantalla, que se obtiene del parámetro deposition
del métodotransformPage()
.El parámetro de
position
indica dónde está ubicada una página en relación con el centro de la pantalla. Es una propiedad dinámica que cambia a medida que el usuario se desplaza por las páginas. Cuando una página llena la pantalla, su valor deposition
es 0. Cuando una página se dibuja justo al lado del lado derecho de la pantalla, su valor deposition
es 1. Si el usuario se desplaza a medio camino entre las páginas uno y dos, la página uno tiene unaposition
de -0.5 y la página dos tiene unaposition
de 0.5. En función de laposition
de las páginas en la pantalla, puede crear animaciones de diapositivas personalizadas estableciendo propiedades de página con métodos comosetAlpha()
,setTranslationX()
osetScaleY()
.
Y esta es la implementación del PageTransformer
que han proporcionado:
public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) { // [-1,1] // Modify the default slide transition to shrink the page as well float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); } // Scale the page down (between MIN_SCALE and 1) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } }
Problema:
Soy incapaz de entender la declaración,
view.setTranslationX(horzMargin - vertMargin / 2);
Mi entendimiento fue que un valor de 1,0 para el parámetro de position
equivale a cubrir el ancho de la pantalla, es decir, w. Por lo tanto, si el centro de una página ha movido x unidades de position
entonces la traducción en términos de pixels / dp sería w * x. Pero están usando un cálculo de margen para el cálculo del importe de la traducción.
¿Puede alguien explicar cómo han hecho este cálculo y lo que estaría mal con mi cálculo?
- Android ViewPager con ScrollViews con ViewPagers dentro de ScrollViews
- Guardar el estado de WebView y restaurar en ANDROID
- ViewPager como una cola circular / envoltura
- Cómo inhabilitar el deslizador abierto en DrawerLayout en Android?
- ViewPager con indicador sin la biblioteca de soporte de Android
- Haga que todo el elemento ViewPager esté alineado al centro cuando PagerAdapter.getPageWidth () <1f
- Cómo establecer el tamaño de ViewPager
- Android AppBarLayout empuja ViewPager hacia abajo
Hay una cosa que falta aquí, el PageTransformer se aplica a las opiniones después de que se han colocado.
Así, con o sin un PageTransformer adjunto a la PageView – cuando se desplaza entre las páginas – simplemente haciendo un desplazamiento (como en un LiseView) con SNAP capacidades.
El PageTransformer sólo agrega efectos encima de eso.
Así que el propósito de,
float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); }
NO es mover las páginas – sino compensar la contracción de la página.
Sin ella, la página tendrá algunos efectos secundarios feos. TRY IT, quitar las líneas 🙂 – Las vistas irán a la derecha / izquierda, pero el posicionamiento estará apagado.
Por lo tanto, la traducción X no mueve la página, pero, en este caso, simplemente gestiona el espaciado de las páginas para mejorar la sensación de la animación – lo anterior es la matemáticas para él. Lo que hace es reducir el espacio entre las páginas en función de la altura / ancho de la pantalla. Primero niega el espacio (horzMargin) luego agrega un poco espaciamiento (- vertMargin / 2)
Y es por eso que su cálculo no es bueno (w * x) – Estás tratando de mover la página – Pero ya se está moviendo.
Al volver a leer su pregunta y esta respuesta, no estoy seguro de haber abordado realmente su pregunta. Creo que puede ser de alguna ayuda, así que lo estoy publicando.
De acuerdo con esto , position = 0 significa que esta página es frontal y central (y para este ejemplo, pantalla completa). Sólo nos preocupa una página con posición en el intervalo de -1 a +1, de lo contrario está demasiado lejos de vista para preocuparse. Puede ver esto en la 1ª y última condiciones en las que alpha se establece en 0, haciendo que la vista sea totalmente transparente.
Soy incapaz de entender la declaración,
view.setTranslationX(horzMargin - vertMargin / 2);
Como lo miré, no vi mucho valor en esta sección de código también. Dado que los márgenes se calculan con base en el scaleFactor, y que está limitado a 0,85 – 1,0, no hace mucha diferencia en la apariencia de la transición. Estoy seguro de que alguien con un ojo mucho mejor para el diseño que yo no estaría de acuerdo. Sin embargo, he eliminado esta parte del código como un experimento.
float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); }
Aunque pude ver pequeñas diferencias dependiendo de la configuración de translationX si me miraba de cerca, nunca lo notaría con el uso ocasional. Más de una diferencia se puede ver estableciendo MIN_SCALE a 0,5 (o menor).
Lo que estaría mal con mi cálculo?
Probablemente nada, siempre y cuando se limita a un pequeño resultado como el código actual. Tenga en cuenta que la clase ViewPager es el controlador principal de la animación en lugar de setTranslationX()
.
GitHub proporciona una biblioteca para la animación que usted quiere sin ningún cálculo
No es necesario crear su PageTransformer de ViewPager personalizado
Simplemente agregue debajo de la biblioteca en su archivo app/build.gradle
.
compile 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:1.2.32@aar'
MainActivity.java
public class MainActivity extends Activity { private static final String KEY_SELECTED_PAGE = "KEY_SELECTED_PAGE"; private static final String KEY_SELECTED_CLASS = "KEY_SELECTED_CLASS"; private int mSelectedItem; private ViewPager mPager; private PageAdapter mAdapter; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int selectedPage = 0; if (savedInstanceState != null) { mSelectedItem = savedInstanceState.getInt(KEY_SELECTED_CLASS); selectedPage = savedInstanceState.getInt(KEY_SELECTED_PAGE); } setContentView(R.layout.activity_main); mAdapter = new PageAdapter(getFragmentManager()); mPager = (ViewPager) findViewById(R.id.container); mPager.setAdapter(mAdapter); try { mPager.setPageTransformer(true, new TransformerItem(ZoomOutSlideTransformer.class).clazz.newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } mPager.setCurrentItem(selectedPage); } public static class PlaceholderFragment extends Fragment { private static final String EXTRA_POSITION = "EXTRA_POSITION"; private static final int[] COLORS = new int[] { 0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444 }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final int position = getArguments().getInt(EXTRA_POSITION); final TextView textViewPosition = (TextView) inflater.inflate(R.layout.fragment_main, container, false); textViewPosition.setText(Integer.toString(position)); textViewPosition.setBackgroundColor(COLORS[position - 1]); return textViewPosition; } } private static final class PageAdapter extends FragmentStatePagerAdapter { public PageAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @Override public Fragment getItem(int position) { final Bundle bundle = new Bundle(); bundle.putInt(PlaceholderFragment.EXTRA_POSITION, position + 1); final PlaceholderFragment fragment = new PlaceholderFragment(); fragment.setArguments(bundle); return fragment; } @Override public int getCount() { return 5; } } private static final class TransformerItem { final String title; final Class<? extends PageTransformer> clazz; public TransformerItem(Class<? extends PageTransformer> clazz) { this.clazz = clazz; title = clazz.getSimpleName(); } @Override public String toString() { return title; } } }
Activity_main.xml
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="MainActivity" />
Fragment_main.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="@string/app_name" android:textColor="@android:color/white" android:textSize="72sp" tools:context="MainActivity$PlaceholderFragment" />
Espero que esto pueda ayudarte. 🙂
Si reduce el rectange por scaleFactor,
Asuma que la altura original es pageHeight y Width es pageWidth;
La nueva altura de contracción será scaleFactor * pageHeight
shrinkMarginTopBottom = pageHeight - scaleFactor * pageHeight = pageHeight(1 - scaleFactor); and I assume it will be equally shirnked from bottom and top; shrinkMarginTop = shrinkMarginTopBottom/2; which is equal to below mentioned formula float vertMargin = pageHeight * (1 - scaleFactor) / 2;
Así que después de explicar los cálculos de margen
float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horzMargin = pageWidth * (1 - scaleFactor) / 2; if (position < 0) { view.setTranslationX(horzMargin - vertMargin / 2); } else { view.setTranslationX(-horzMargin + vertMargin / 2); }
La traducción x debe tener un cierto desplazamiento para las posiciones de página 0 y 1 para obtener el efecto de animación y cierta distancia restando los márgenes para ambos … La división ocurre porque + ve y -ve x traducción se suma al margen exacto
Puedo estar adivinando pero para mí tener una variable x traducción y margen que varía con el factor de escala, vertMargin se utiliza para crear ese desplazamiento que varía con la escala .. si se quita el código vertMargin seguirá animando lo mismo, pero un poco más rápido Pero sin mantener ningún margen entre dos páginas.
- Transparente AlertDialog tiene fondo negro
- Android Mejor manera de detectar y manejar el usuario INACTIVIDAD