web-dev-qa-db-fra.com

Menu et masquer automatiquement FloatingActionButton de la bibliothèque de support de conception Android

J'utilise Android Design Support Library et je veux un FloatingActionButton doté du masquage automatique par défilement. 

ma mise en page est:

<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 toujours affiché lors du défilement de texte, je souhaite le masquer automatiquement lors du défilement de texte.

Et, je veux avoir un menu FloatingActionButton en cliquant sur FloatingActionButton, comme ceci:

enter image description here

9
AliSh

FloatingActionButton qui ont AutoHide par Scrolling,

Vous devez utiliser Android.support.v4.widget.NestedScrollView au lieu de ScrollView. Vous ne pouvez pas utiliser le ScrollView. Vous devez utiliser NestedScrollView ou une vue qui implémente l'interface NestedScrollingChild, comme un RecyclerView.

Pour obtenir ce type de modèle, vous devez implémenter votre Behavior personnalisée. Un code de Nice posté par un googleur masque le FAB lorsque l'utilisateur fait défiler l'écran vers le bas et l'affiche lorsqu'il fait défiler vers le haut. Réutilise la même animation que celle utilisée par FloatingActionButton.Behavior pour masquer/afficher le FAB en réaction à la sortie/entrée de AppBarLayout.

ACTUALISÉE LE 18/07/2015

Avec le 22.2.1 vous pouvez simplement ajouter le code affiché ci-dessous, en utilisant les animations prédéfinies. Utilisez simplement une classe comme celle-ci: (source originale ici )

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();
        }
    }
}

Ensuite, vous pouvez appliquer ce comportement à votre FAB en utilisant:

<Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab"
     app:layout_behavior="com.support.Android.designlibdemo.ScrollAwareFABBehavior" />

Avec Design 22.2.0 : Vous devez utiliser une classe comme celle-ci: (source originale ici )

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);
        }
    }
}

Ensuite, vous pouvez appliquer ce comportement à votre FAB en utilisant:

<Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab"
     app:layout_behavior="com.support.Android.designlibdemo.ScrollAwareFABBehavior" />

Bien sûr, vous pouvez changer ce code pour obtenir votre motif préféré.

Et, je veux avoir un menu FloatingActionButton en cliquant sur FloatingActionButton, comme ceci:

Actuellement, le FAB d'origine ne prend pas en charge ce modèle. Vous devez implémenter un code personnalisé pour y parvenir.

31
Gabriele Mariotti

Vous pouvez y arriver 

Voici mon code. 

Étape 1:

Commencez par créer Getter of FloatingActionMenu pour pouvoir l'appeler depuis une autre activité ou depuis un fragment où votre recycleview est utilisé.

public FloatingActionMenu getFloatingActionMenu() {
        return fabMenu;
    }

Étape 2:

Appelez ci-dessous la ligne d'une autre activité ou d'un fragment 

   FloatingActionMenu fabMenu=((MainActivity)getActivity()).getFloatingActionMenu();

Étape 3:

Maintenant, vérifiez si recycleview est en train de défiler ou ne dépend pas de la position "dy" Ici, j'ai utilisé animation 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);
                }
            }
        });

Remarque: Si vous souhaitez masquer FloatingActionButton lors du défilement, utilisez le même code que dans FloatingActionMenu.

Je vous remercie.

1
Ulearn

Vous pouvez implémenter le menu d'actions flottantes en utilisant this .

En ce qui concerne l'animation pour le menu d'actions flottantes, vous pouvez créer une classe appelée 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);
        }
    }
}

Notez que R.anim.fab_in et R.anim.fab_out sont remplacées par R.anim.design_fab_in et R.anim.design_fab_out respectivement.

Utilisez-le dans le 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>
0
Noel Chew