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:
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.
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.
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>