usar studio floatingactionbutton como color bootstrap android floating-action-button android-fab

android - studio - floating action button menu



¿Cómo cambiar FloatingActionButton entre pestañas? (7)

A continuación se muestra la forma sencilla de lograr el resultado deseado.

Agregue dos (o equivalentes a las acciones de la pestaña) FloatingActionButton en su actividad principal como a continuación

<android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/appbar_padding_top" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay"> </android.support.v7.widget.Toolbar> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fabChat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" android:src="@drawable/ic_fab_chat" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fabPerson" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" android:src="@drawable/ic_fab_person" android:visibility="gone" />

Ahora en su MainActivity.java use las funciones predeterminadas de Fab para ocultar y mostrar en cada selección de pestaña como se muestra a continuación

private void animateFab(int position) { switch (position) { case 0: fabChat.show(); fabPerson.hide(); break; case 1: fabPerson.show(); fabChat.hide(); break; default: fabChat.show(); fabPerson.hide(); break; } }

Llame a la función animateFab como abajo

TabLayout.OnTabSelectedListener onTabSelectedListener = new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { animateFab(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }; ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { animateFab(position); } @Override public void onPageScrollStateChanged(int state) { } };

Estoy tratando de implementar FloatingActionButton de Google Design Support Library en dos de las tres pestañas, y de acuerdo con las Pautas de diseño de materiales - FloatingActionButton dice:

Si hay un botón de acción flotante en varias pantallas laterales (como en las pestañas), al ingresar a cada pantalla, el botón debe mostrarse y ocultarse si la acción contenida en cada una es diferente. Si la acción es la misma, el botón debe permanecer en la pantalla (y traducirse a una nueva posición, si es necesario).

¿Cómo puedo hacer este tipo de transición o animación para los botones FAB en mi aplicación?


Ampliando las respuestas de blackcj y kirtan403, también he agregado la capacidad de ocultar la fab en una pestaña elegida (en este caso, la primera pestaña), que responde a la pregunta de bernzkie bajo la respuesta de blackcj.

Para lograr esto, primero declaré int[] ''s con 3 elementos, cada uno para el fab de cada una de las 3 pestañas. Establecí el primer elemento en cada uno en 0 porque será la fábrica invisible de la primera pestaña que no necesita recursos.

int[] colorIntArray = {0, R.color.fab_red, R.color.fab_green}; int[] iconIntArray = {0, R.drawable.fab_pencil, R.drawable.fab_chevron};

A continuación, establezco una instrucción if en el método onCreate de la Activity que presenta la fab y las pestañas. Esta declaración oculta el fab y lo reduce, de modo que cuando se hace visible de nuevo, se puede hacer que solo aumente la escala, no la reduzca innecesariamente, y luego la vuelva a subir. Configuré la escala para que coincida con la escala final de la animación de reducción de blackcj.

if (tabLayout.getSelectedTabPosition() == 0) { // if on the 1st tab fab.hide(); // scale down to only scale up when switching from 1st tab fab.setScaleX(0.2f); fab.setScaleY(0.2f); }

Luego, fuera del método onCreate , agregué el método animateFab de animateFab , con la modificación de rotate de kirtan403. Sin embargo, modifiqué el método animateFab para tener también una declaración condicional, donde:

  • si regresa a la primera pestaña, la fab está oculta (se reduce automáticamente cuando se esconde);

  • cuando se cambia de una pestaña en la que el fab ya es de tamaño completo y se puede ver en otra pestaña en la que se pretende que sea visible, realiza la animación a escala completa, cambio y ampliación;

  • cuando se cambia de la pestaña con el fab oculto (en este caso la primera pestaña), el fab se hace visible, luego se escala (no se reduce, luego se escala) con la animación personalizada.

    protected void animateFab(final int position) { fab.clearAnimation(); if (tabLayout.getSelectedTabPosition() == 0) { // if on the 1st tab fab.hide(); } else if (fab.getScaleX() == 1f) { // if the fab is full scale // Scale down animation ScaleAnimation shrink = new ScaleAnimation(1f, 0.2f, 1f, 0.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); shrink.setDuration(150); // animation duration in milliseconds shrink.setInterpolator(new DecelerateInterpolator()); shrink.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // Change FAB color and icon fab.setBackgroundTintList(getResources().getColorStateList(colorIntArray[position])); fab.setImageDrawable(getResources().getDrawable(iconIntArray[position], null)); // Scale up animation ScaleAnimation expand = new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); expand.setDuration(100); // animation duration in milliseconds expand.setInterpolator(new AccelerateInterpolator()); // Rotate Animation Animation rotate = new RotateAnimation(60.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(200); rotate.setInterpolator(new DecelerateInterpolator()); // Add both animations to animation state AnimationSet animationSet = new AnimationSet(false); //false means don''t share interpolators animationSet.addAnimation(expand); animationSet.addAnimation(rotate); fab.startAnimation(animationSet); } @Override public void onAnimationRepeat(Animation animation) { } }); fab.startAnimation(shrink); } else { // if the fab is already scaled down // Change FAB color and icon fab.setBackgroundTintList(getResources().getColorStateList(colorIntArray[position])); fab.setImageDrawable(getResources().getDrawable(iconIntArray[position], null)); fab.show(); // Scale up animation ScaleAnimation expand = new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); expand.setDuration(100); // animation duration in milliseconds expand.setInterpolator(new AccelerateInterpolator()); // Rotate Animation Animation rotate = new RotateAnimation(60.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(200); rotate.setInterpolator(new DecelerateInterpolator()); // Add both animations to animation state AnimationSet animationSet = new AnimationSet(false); //false means don''t share interpolators animationSet.addAnimation(expand); animationSet.addAnimation(rotate); fab.startAnimation(animationSet); } }

Luego, simplemente agregué el detector de selección de pestañas sin cambios de onCreate método onCreate .

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { viewPager.setCurrentItem(tab.getPosition()); animateFab(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });

Espero que esto ayude, ciertamente funciona perfectamente para mí. Gracias a blackcj & kirtan403. :)


Eso fue lo que funcionó para mí:

private boolean isFloatingActionButtonHidden = false; private int[] colorIntArray = {R.color.walking,R.color.running,R.color.biking,R.color.paddling,R.color.golfing}; private int[] iconIntArray = {R.drawable.ic_walk_white,R.drawable.ic_run_white,R.drawable.ic_bike_white,R.drawable.ic_add_white,R.drawable.ic_arrow_back_white}; viewPager.addOnPageChangeListener(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) { switch (state) { case ViewPager.SCROLL_STATE_SETTLING: // This is triggered just before the view pager reaches the final state // if you want to trigger the animation after the page reaches its final position // just move this to "case ViewPager.SCROLL_STATE_IDLE:" showFloatingActionButton(viewPager.getCurrentItem()); break; case ViewPager.SCROLL_STATE_IDLE: // This is only triggered if user pulls to the left of the start or right of the end if (isFloatingActionButtonHidden) { showFloatingActionButton(viewPager.getCurrentItem()); } break; default: // in all other cases just hide the fab if it is not visable if (!isFloatingActionButtonHidden) { hideFloatingActionButton(); } } } }); private void showFloatingActionButton(int position) { fab.setImageDrawable(getResources().getDrawable(iconIntArray[position], null)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ floatingActionButton.setBackgroundTintList(getResources().getColorStateList(iconIntArray[position], getTheme())); } else { floatingActionButton.setBackgroundTintList(getResources().getColorStateList(iconIntArray[position])); } floatingActionButton.show(); } private void hideFloatingActionButton() { isFloatingActionButtonHidden = true; floatingActionButton.hide(); }


Esta funcionalidad no está actualmente integrada en el botón de acción flotante, por lo que tendrá que animarlo usted mismo. Suponiendo que su FloatingActionButton esté en su actividad principal, agregue la siguiente función a su actividad.

int[] colorIntArray = {R.color.walking,R.color.running,R.color.biking,R.color.paddling,R.color.golfing}; int[] iconIntArray = {R.drawable.ic_walk_white,R.drawable.ic_run_white,R.drawable.ic_bike_white,R.drawable.ic_add_white,R.drawable.ic_arrow_back_white}; protected void animateFab(final int position) { fab.clearAnimation(); // Scale down animation ScaleAnimation shrink = new ScaleAnimation(1f, 0.2f, 1f, 0.2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); shrink.setDuration(150); // animation duration in milliseconds shrink.setInterpolator(new DecelerateInterpolator()); shrink.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // Change FAB color and icon fab.setBackgroundTintList(getResources().getColorStateList(colorIntArray[position])); fab.setImageDrawable(getResources().getDrawable(iconIntArray[position], null)); // Scale up animation ScaleAnimation expand = new ScaleAnimation(0.2f, 1f, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); expand.setDuration(100); // animation duration in milliseconds expand.setInterpolator(new AccelerateInterpolator()); fab.startAnimation(expand); } @Override public void onAnimationRepeat(Animation animation) { } }); fab.startAnimation(shrink); }

Actualice los recursos de color y dibujo para que coincida con su proyecto. Agregue un detector de selección de pestañas en su método onCreate y llame a la función animar cuando se seleccione una pestaña.

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { mViewPager.setCurrentItem(tab.getPosition()); animateFab(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });

Asegúrese de tener suficientes colores e iconos que coincidan con la cantidad de pestañas que tiene.


Extendiendo la respuesta de blackcj, La solución funcionó realmente bien como se explicó. Sin embargo me gustaría añadir algo en eso.

He visto ese video en cámara lenta. Lo dibujable y lo fabuloso se animan de manera diferente. Cuando se esconden, fab y drawable están sincronizados. Mientras se muestra, fab regresa primero, y luego de completar el 60-70 por ciento, la animación de inicio dibujable de 0 y la rotación y la escala se convierten en tamaño completo.

Sin embargo, no pude lograr la animación dibujable saperatly. Pero, logré rotar y escalar con diferentes interpoladores y un tiempo ligeramente modificado. Así que parece más como en el video que también se presenta en las directrices de diseño de Google.

int[] colorIntArray = {R.color.red,R.color.gray,R.color.black}; int[] iconIntArray = {R.drawable.ic_btn1, R.drawable.ic_btn2, R.drawable.ic_btn3}; protected void animateFab(final int position) { fab.clearAnimation(); // Scale down animation ScaleAnimation shrink = new ScaleAnimation(1f, 0.1f, 1f, 0.1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); shrink.setDuration(100); // animation duration in milliseconds shrink.setInterpolator(new AccelerateInterpolator()); shrink.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // Change FAB color and icon fab.setBackgroundTintList(ContextCompat.getColorStateList(getApplicationContext(), colorIntArray[position])); fab.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), iconIntArray[position])); // Rotate Animation Animation rotate = new RotateAnimation(60.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(150); rotate.setInterpolator(new DecelerateInterpolator()); // Scale up animation ScaleAnimation expand = new ScaleAnimation(0.1f, 1f, 0.1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); expand.setDuration(150); // animation duration in milliseconds expand.setInterpolator(new DecelerateInterpolator()); // Add both animations to animation state AnimationSet s = new AnimationSet(false); //false means don''t share interpolators s.addAnimation(rotate); s.addAnimation(expand); fab.startAnimation(s); } @Override public void onAnimationRepeat(Animation animation) { } }); fab.startAnimation(shrink); }

Y tab tab tabulador de escucha como de costumbre:

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { mViewPager.setCurrentItem(tab.getPosition()); animateFab(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });


Finalmente, encontré una solución que es bastante fácil y muestra una animación que es exactamente como el gif adjunto: en las soluciones de @ Nauman''s oder @ Omid, la animación del programa comienza antes de que termine la animación de ocultar. ¡Pero asegúrese de usar la biblioteca de soporte más nueva! Lo he probado con la versión 23.2.1.

Caso de uso:

  • Mostrar fab 1 en la pestaña 1 (índice 0)
  • Mostrar fab 2 en la pestaña 2 (índice 1)
  • No mostrar ninguna fab en la pestaña 3 (índice 2)

En su xml, coloque en fabs con identificadores únicos y visibilidad establecida como invisible:

<android.support.design.widget.FloatingActionButton android:id="@+id/fab1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/some_icon" android:visibility="invisible" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" android:src="@drawable/another_icon" android:visibility="invisible" />

Luego, agregue dos campos para sus fabs a su Actividad (también puede usar variables locales u obtener la Vista cada vez con findViewById(...) ):

public class MainActivity extends AppCompatActivity { private FloatingActionButton fab1; private FloatingActionButton fab2;

En su función onCreate(...) , busque estas vistas y onCreate(...) en los campos declarados:

fab1 = (FloatingActionButton) findViewById(R.id.fab1); fab2 = (FloatingActionButton) findViewById(R.id.fab2);

Luego declare una función que muestre la fábrica correcta para la posición dada. El caso predeterminado (pestaña 3 o más) es bastante sencillo: simplemente llame al método hide() en las fabs. show() y hide() ya implementan una animación de escalado. Pero si ocultamos fab2 en la pestaña 1, tenemos que esperar hasta que haya terminado antes de poder mostrar fab1. Así que establezca un FloatingActionButton.OnVisibilityChangedListener como parámetro para el método hide(...) y muestre la nueva onHidden(...) deseada en el onHidden(...) de ese oyente. El resultado es este:

public void showRightFab(int tab) { switch (tab) { case 0: fab2.hide(new FloatingActionButton.OnVisibilityChangedListener() { @Override public void onHidden(FloatingActionButton fab) { fab1.show(); } }); break; case 1: fab1.hide(new FloatingActionButton.OnVisibilityChangedListener() [ @Override public void onHidden(FloatingActionButton fab) { fab2.show(); } }); break; default: fab1.hide(); fab2.hide(); break; } }

Esa fue la parte más difícil! Ahora agregue un oyente al ViewPager para llamar a la función showRightFab(...) cada vez que cambie la pestaña seleccionada.

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { showRightFab(position); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageScrollStateChanged(int state) {} });

Por último, llame a la función una vez manualmente en el onCreate(...) para mostrar el fab en la pestaña predeterminada, ya que el ViewPager.OnPageChangeListener onPageSelected(...) no se llama en el inicio (por ej. si abres la aplicación y muestra la pestaña 1, no se mostrará ninguna fab porque nunca se ha llamado a la función showRightFab(...) ).

showRightFab(viewPager.getCurrentItem());

¡Ese trabajo está perfectamente en mi aplicación!


puede agregar un oyente a viewpager y mostrar y ocultar fab según su estado cuando comience a desplazar el viewpager, este es el orden de estados SCROLL_STATE_DRAGGING SCROLL_STATE_SETTLING SCROLL_STATE_IDLE

por ejemplo:

viewPager.addOnPageChangeListener(this); @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_IDLE) fab.show(); else if(state==ViewPager.SCROLL_STATE_DRAGGING) fab.hide(); }