Menu y Autohide FloatingActionButton de Android Design Support Library
Estoy usando Android Design Support Library y quiero un FloatingActionButton que tenga AutoHide por Scrolling,
Mi diseño es:
- ¿Cómo replicar el botón de acción flotante Inbox (con texto para cada botón secundario)?
- Android: cambiar dinámicamente el icono FAB (botón de acción flotante) del código
- Establecer FAB (botón de acción flotante) encima del teclado
- Botón de acción flotante que no se muestra sobre la vista de reciclaje (que se encuentra dentro de un DrawerLayout)
- Botón de acción flotante Ser un cuadrado
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/LargeText" /> </ScrollView> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchorGravity="bottom|right|end" app:layout_anchor="@id/scrollView" android:src="@drawable/abc_btn_rating_star_off_mtrl_alpha" /> </android.support.design.widget.CoordinatorLayout>
FloatingActionButton que muestra siempre al desplazar el texto, quiero ocultarlo automáticamente al desplazar el texto.
Y, quiero tener un menú FloatingActionButton haciendo clic en FloatingActionButton, como esto:
- No puedo eliminar el valor predeterminado de FloatingActionButton en una actividad de Gaveta de navegación
- Android L FAB Botón sombra
- Implementación del menú de acción flotante mediante el botón de acción Float de Android Design Support library
- Android animateLayoutChanges y flicker anclado fab
- Android - FAB para ocultar al navegar entre diferentes fragmentos en un viewpager
- Android No se puede anclar el botón FAB a BottomSheet
- Uso de Google Design Library como ocultar el botón FAB en Desplazamiento hacia abajo?
- Diseño de soporte para Android elevación del botón de acción flotante no visible para los colores distintos del blanco
FloatingActionButton que tiene AutoHide por Desplazamiento,
Debe utilizar android.support.v4.widget.NestedScrollView
lugar de ScrollView
. No puede utilizar ScrollView. Debe utilizar el NestedScrollView o una vista que implemente la interfaz NestedScrollingChild, como un RecyclerView.
Para lograr este tipo de patrón que tiene que implementar su Behavior
personalizado. Hay un bonito código publicado por un Googler que oculta el FAB cuando el usuario se desplaza hacia abajo y lo muestra cuando se desplaza hacia arriba. Reutiliza la misma animación que FloatingActionButton.Behavior utiliza para ocultar / mostrar el FAB en reacción a la salida / entrada de AppBarLayout.
ACTUALIZADO 18/07/2015
Con el 22.2.1 simplemente puede agregar el código publicado a continuación, utilizando las animaciones preconstruidas. Sólo usa una clase como esta: (fuente original aquí )
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View directTargetChild, final View target, final int nestedScrollAxes) { // Ensure we react to vertical scrolling return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View target, final int dxConsumed, final int dyConsumed, final int dxUnconsumed, final int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB child.hide(); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB child.show(); } } }
A continuación, puede aplicar este comportamiento a su FAB utilizando:
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" app:layout_behavior="com.support.android.designlibdemo.ScrollAwareFABBehavior" />
Con Diseño 22.2.0 : Tienes que usar una clase como esta: (fuente original aquí )
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); private boolean mIsAnimatingOut = false; public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View directTargetChild, final View target, final int nestedScrollAxes) { // Ensure we react to vertical scrolling return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View target, final int dxConsumed, final int dyConsumed, final int dxUnconsumed, final int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB animateOut(child); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB animateIn(child); } } // Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits private void animateOut(final FloatingActionButton button) { if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer() .setListener(new ViewPropertyAnimatorListener() { public void onAnimationStart(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = true; } public void onAnimationCancel(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; } public void onAnimationEnd(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; view.setVisibility(View.GONE); } }).start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out); anim.setInterpolator(INTERPOLATOR); anim.setDuration(200L); anim.setAnimationListener(new Animation.AnimationListener() { public void onAnimationStart(Animation animation) { ScrollAwareFABBehavior.this.mIsAnimatingOut = true; } public void onAnimationEnd(Animation animation) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; button.setVisibility(View.GONE); } @Override public void onAnimationRepeat(final Animation animation) { } }); button.startAnimation(anim); } } // Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters private void animateIn(FloatingActionButton button) { button.setVisibility(View.VISIBLE); if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).scaleX(1.0F).scaleY(1.0F).alpha(1.0F) .setInterpolator(INTERPOLATOR).withLayer().setListener(null) .start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in); anim.setDuration(200L); anim.setInterpolator(INTERPOLATOR); button.startAnimation(anim); } } }
A continuación, puede aplicar este comportamiento a su FAB utilizando:
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" app:layout_behavior="com.support.android.designlibdemo.ScrollAwareFABBehavior" />
Por supuesto, puede cambiar este código para obtener su patrón favorito.
Y, quiero tener un menú FloatingActionButton haciendo clic en FloatingActionButton, como esto:
Actualmente, el FAB original no admite este patrón. Tienes que implementar un código personalizado para lograrlo.
Puedes lograrlo
Aquí está mi código.
Paso 1:
Primero haz Getter de FloatingActionMenu para que puedas llamarlo desde otra actividad o desde fragmento donde se usa tu recycleview
public FloatingActionMenu getFloatingActionMenu() { return fabMenu; }
Paso 2:
Llame debajo de la línea de otra actividad o de fragmento
FloatingActionMenu fabMenu=((MainActivity)getActivity()).getFloatingActionMenu();
Paso 3:
Ahora compruebe cuánto recycleview está desplazándose o no depende de la posición "dy" Aquí he usado la animación fabMenu
Animation FabMenu_fadOut = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_out); Animation FabMenu_fadIn = AnimationUtils.loadAnimation(getActivity(), R.anim.abc_grow_fade_in); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 0 && floatingActionButton.isShown()) { //fabMenu.startAnimation(FabMenu_fadIn); fabMenu.setVisibility(View.GONE); } if (dy < 0 && !floatingActionButton.isShown()) { // fabMenu.startAnimation(FabMenu_fadOut); fabMenu.setVisibility(View.VISIBLE); } } });
Nota: Si desea ocultar FloatingActionButton en desplazamiento, utilice el mismo código que en FloatingActionMenu.
Gracias.
Usted puede implementar el menú de acción flotante usando esto .
En cuanto al menú de animación para acciones flotantes, puede crear una clase llamada ScrollAwareFloatingActionMenuBehaviour:
public class ScrollAwareFloatingActionMenuBehaviour extends CoordinatorLayout.Behavior<FloatingActionsMenu> { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); private boolean mIsAnimatingOut = false; private boolean mIsAnimatingIn = false; public ScrollAwareFloatingActionMenuBehaviour(Context context, AttributeSet attrs) { } @Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View directTargetChild, View target, int nestedScrollAxes) { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 10 && !this.mIsAnimatingOut && !this.mIsAnimatingIn && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB animateOut(child); } else if (dyConsumed < -10 && !this.mIsAnimatingOut && !this.mIsAnimatingIn && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB animateIn(child); } } // Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits private void animateOut(final FloatingActionsMenu button) { if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).translationYBy(200F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer() .setListener(new ViewPropertyAnimatorListener() { public void onAnimationStart(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = true; } public void onAnimationCancel(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; } public void onAnimationEnd(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; view.setVisibility(View.GONE); } }).start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.design_fab_out); anim.setInterpolator(INTERPOLATOR); anim.setDuration(200L); anim.setAnimationListener(new Animation.AnimationListener() { public void onAnimationStart(Animation animation) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = true; } public void onAnimationEnd(Animation animation) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; button.setVisibility(View.GONE); } @Override public void onAnimationRepeat(final Animation animation) { } }); button.startAnimation(anim); } } // Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters private void animateIn(FloatingActionsMenu button) { button.setVisibility(View.VISIBLE); if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).translationYBy(-200F).alpha(1.0F) .setInterpolator(INTERPOLATOR).withLayer().setListener(new ViewPropertyAnimatorListener() { @Override public void onAnimationStart(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = true; } @Override public void onAnimationEnd(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = false; } @Override public void onAnimationCancel(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = false; } }) .start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), android.support.design.R.anim.design_fab_in); anim.setDuration(200L); anim.setInterpolator(INTERPOLATOR); button.startAnimation(anim); } } }
Observe que R.anim.fab_in y R.anim.fab_out son reemplazados por R.anim.design_fab_in y R.anim.design_fab_out respectivamente.
Utilícelo en el xml:
<com.getbase.floatingactionbutton.FloatingActionsMenu xmlns:fab="http://schemas.android.com/apk/res-auto" android:id="@+id/fab_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" fab:fab_addButtonColorNormal="@color/colorAccent" fab:fab_addButtonColorPressed="@color/colorAccentLight" fab:fab_addButtonPlusIconColor="@android:color/white" app:layout_behavior="com.example.widgets.behaviour.ScrollAwareFloatingActionMenuBehaviour" fab:fab_labelStyle="@style/menu_labels_style" fab:fab_labelsPosition="left"> <com.getbase.floatingactionbutton.FloatingActionButton android:id="@+id/fab_share" android:layout_width="wrap_content" android:layout_height="wrap_content" fab:fab_colorNormal="@color/fab_normal_blue" fab:fab_colorPressed="@color/fab_normal_blue_pressed" fab:fab_icon="@drawable/ic_social_share" fab:fab_title="@string/fab_menu_group_chat" /> </com.getbase.floatingactionbutton.FloatingActionsMenu>
- Disminuir el tamaño de la barra de clasificación en Android 2.1
- Cómo utilizar setOutlineProvider en lugar de setOutline en Lollipop