web-dev-qa-db-fra.com

FloatingActionButton ne cache pas

J'essaie de masquer mon FloatingActionButton fabLocation par programme avec:

fabLocation.setVisibility(View.GONE)

mais ça ne marche pas.

Si j'ajoute Android:visibility="gone" dans ma disposition XML, fabLocation est masqué lorsque j'exécute mon activité, mais il réapparaît lorsque je fais défiler.

Voici ma mise en page:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/main_content"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true">

<Android.support.design.widget.AppBarLayout
    Android:id="@+id/appbar"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:fitsSystemWindows="true"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fitsSystemWindows="true"
        app:contentScrim="@color/colorOverlay"
        app:expandedTitleMarginEnd="64dp"
        app:expandedTitleMarginStart="48dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            Android:id="@+id/img_couverture"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:fitsSystemWindows="true"
            Android:scaleType="centerCrop"
            Android:src="@drawable/bg_navigation_drawer_header"
            app:layout_collapseMode="parallax" />

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    </Android.support.design.widget.CollapsingToolbarLayout>

</Android.support.design.widget.AppBarLayout>

<Android.support.v4.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical">

        <Android.support.v7.widget.CardView
            Android:layout_marginTop="8dp"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

            <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:orientation="vertical"
                Android:padding="16dp">

                <TextView
                    Android:id="@+id/tv_name"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:textSize="18sp" />

                <View
                    Android:background="@drawable/separator_orange_gradient"
                    Android:layout_marginTop="8dp"
                    Android:layout_marginBottom="16dp"
                    Android:layout_width="match_parent"
                    Android:layout_height="2dp"/>

                <TextView
                    Android:id="@+id/tv_history"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:textAppearance="@style/TextAppearance.RobotoLight" />

            </LinearLayout>

        </Android.support.v7.widget.CardView>

    </LinearLayout>

</Android.support.v4.widget.NestedScrollView>

<Android.support.design.widget.FloatingActionButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_margin="16dp"
    Android:clickable="true"
    Android:id="@+id/fab_location"
    Android:src="@drawable/ic_fab_location_24dp"
    app:backgroundTint="@color/colorOrange"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="bottom|right|end" />

33
frenchdev20

Cela est dû à l'attribut app:layout_anchor. Vous devez vous débarrasser de l'ancre avant de modifier la visibilité:

CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.setVisibility(View.GONE);
43
natario

Les boutons FloatingAction ancrés à AppBarLayouts ont une relation spéciale dans laquelle leur visibilité est contrôlée par la position de défilement de AppBarLayout.

Vous pouvez désactiver ceci via l'attribut behavior_autoHide:

<Android.support.design.widget.FloatingActionButton
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:layout_anchor="..."
    app:behavior_autoHide="false"/>

Vous pouvez également le faire par programme si vous le souhaitez:

FloatingActionButton.Behavior b
    = (FloatingActionButton.Behavior) fab.getBehavior();
b.setAutoHideEnabled(false);
10
Chris Banes

Si vous voulez montrer un FAB caché

    <Android.support.design.widget.CoordinatorLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/coordinator"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:fitsSystemWindows="true">


    <Android.support.design.widget.AppBarLayout
            Android:id="@+id/appbar"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            Android:fitsSystemWindows="true">
    ...

    </Android.support.design.widget.AppBarLayout>

    ...

    <Android.support.design.widget.FloatingActionButton
            Android:id="@+id/fab"
            Android:visibility="gone"
            Android:layout_height="wrap_content"
            Android:layout_width="wrap_content"
            Android:clickable="true"/>

</Android.support.design.widget.CoordinatorLayout>

et

    CoordinatorLayout.LayoutParams p = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.WRAP_CONTENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT);
    p.anchorGravity = Gravity.BOTTOM | Gravity.END;
    p.setAnchorId(R.id.appbar);
    p.setMargins(...);
    fab.setLayoutParams(p);
    fab.setVisibility(View.VISIBLE);
5
Georgy Gobozov

Je n'étais complètement satisfait d'aucune des solutions publiées. Certains travaillaient seulement une partie du temps, alors que d'autres ne travaillaient que pour fab.setVisibility(). Bien que je sache que c’est techniquement ce que la question initiale posait, quelques réponses ont exprimé un intérêt pour l’utilisation de fab.hide(), et se moquer des paramètres de mise en page n’arrive pas exactement à la racine du problème.

Comme l'a souligné @ChrisBanes, le FloatingActionButton.Behavior étant lié à la AppBarLayout est la cause du problème. Donc, comme pour sa réponse, vous devez setAutoHideEnabled(false) pour désactiver cette fonctionnalité. Mais cette solution n’aide en rien si vous souhaitez que la variable FloatingActionButton se cache automatiquement et lorsque vous appelez hide() manuellement.

Donc, pour faire ceci; Je désactive simplement la fonctionnalité de masquage automatique avant de masquer manuellement la Button, puis la réactiver après avoir affiché manuellement la Button:

private void hideFloatingActionButton(FloatingActionButton fab) {
    CoordinatorLayout.LayoutParams params =
            (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
    FloatingActionButton.Behavior behavior =
            (FloatingActionButton.Behavior) params.getBehavior();

    if (behavior != null) {
        behavior.setAutoHideEnabled(false);
    }

    fab.hide();
}

private void showFloatingActionButton(FloatingActionButton fab) {
    fab.show();
    CoordinatorLayout.LayoutParams params =
            (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
    FloatingActionButton.Behavior behavior =
            (FloatingActionButton.Behavior) params.getBehavior();

    if (behavior != null) {
        behavior.setAutoHideEnabled(true);
    }
}
5
Bryan
FloatingActionButton layers = (FloatingActionButton) findViewById(R.id.layers);
layers.hide();

Cela fonctionne pour moi, setVisibility ne fonctionne pas pour FloatingActionButton car il appartient à une autre viewGroup qui n'a pas de méthode setVisibility.

3
Satendra Behre

Après quelques réponses, j'ai trouvé la solution à mon problème (même si la fab est cachée, elle peut gérer l'action!).

Tout d'abord, je vous suggère de remplacer .setVisibility(View.GONE) et .setVisibility(View.VISIBLE) par les méthodes .show() et .hide(). Ces derniers manipulent aussi actionMode.

Le deuxième problème pour moi était l'action également gérée lorsque la fab était cachée. Pour résoudre ceci, je l'ai faite:

final CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams)floatingActionButton.getLayoutParams();
    if (show){
        p.setAnchorId(R.id.appBarLayout);
        p.width = CoordinatorLayout.LayoutParams.WRAP_CONTENT;
        p.height = CoordinatorLayout.LayoutParams.WRAP_CONTENT;
        floatingActionButton.setLayoutParams(p);
        floatingActionButton.show();
    }else{
        p.setAnchorId(View.NO_ID);
        p.width = 0;
        p.height = 0;
        floatingActionButton.setLayoutParams(p);
        floatingActionButton.hide();
    }
2
ciccioska

La vraie solution à votre problème est de sous-classer la valeur par défaut FloatingActionButton.Behavior pour appeler setAutoHide(false) dans leurs constructeurs, afin que vous puissiez le contrôler vous-même.

Notez que je parle des feuilles du bas ci-dessous, mais c'est exactement le même problème pour tous les boutons d'action flottants ancrés, et cela répond à la question et devrait résoudre le problème comme prévu.

Sinon, vous pouvez remplacer la méthode boolean onDependentViewChanged(…) de votre comportement personnalisé, copier la méthode statique isBottomSheet(…) présente dans la classe FloatingActionButton.Behavior et appeler et renvoyer uniquement la valeur de la super méthode si ce n'est pas une feuille de fond.

Vous pouvez personnaliser davantage le comportement par défaut de cette manière ou en étendant directement la classe Vanilla CoordinatorLayout.Behavior. Vous pouvez également sélectionner le code à copier pour copier-coller à partir de la classe FloatingActionButton.Behavior si nécessaire.

Voici le code que j'ai utilisé pour contrôler la visibilité de FAB:

/**
 * Allows controlling the FAB visibility manually.
 */
@SuppressWarnings("unused")
public class FabManualHideBehavior extends FloatingActionButton.Behavior {

    public FabManualHideBehavior() {
        super();
        setAutoHideEnabled(false);
    }

    public FabManualHideBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        setAutoHideEnabled(false);
    }
}

Et je l'ai appliqué à mon FAB en XML de cette façon:

<Android.support.design.widget.CoordinatorLayout
    ...>
    ...
    <Android.support.design.widget.FloatingActionButton
        ...
        app:layout_anchor="@+id/bottom_sheet"
        app:layout_anchorGravity="top|end"
        app:layout_behavior="your.package.name.ui.behavior.FabManualHideBehavior"/>

</Android.support.design.widget.CoordinatorLayout>
1
Louis CAD

Aucune de ces solutions ne m'a aidé à 100%. J'avais besoin de montrer et de masquer de manière répétée et animée (comme FAB.show() et hide()) tout en étant ancré à la barre d'applications lorsqu'il était visible. 

J'ai fini par créer le nouveau FAB à chaque fois que je le montrais, l'insérant et le fixant manuellement, et l'animant en fonction de l'implémentation de la bibliothèque de support. C'est dégueulasse, mais ça fonctionne parfaitement.

private void hidePlayButton(final FloatingActionButton fab) {
    // Cancel any animation from the default behavior
    fab.animate().cancel();
    fab.animate()
               .scaleX(0f)
               .scaleY(0f)
               .alpha(0f)
               .setDuration(200)
               .setInterpolator(new FastOutLinearInInterpolator())
               .setListener(new Animator.AnimatorListener() {
                   @Override public void onAnimationStart(Animator animation) {}

                   @Override public void onAnimationEnd(Animator animation) {
                      coordinatorLayout.removeView(fab);
                   }

                   @Override public void onAnimationCancel(Animator animation) {}

                   @Override public void onAnimationRepeat(Animator animation) {}
               });
}

private void showPlayButton() {
    int fabSize = getResources().getDimensionPixelSize(R.dimen.fab_size);
    int margin = getResources().getDimensionPixelSize(R.dimen.fab_margin);
    final FloatingActionButton fab = new FloatingActionButton(getActivity());
    fab.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(getActivity(), R.color.tint)));
    fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.play));
    CoordinatorLayout.LayoutParams p = new CoordinatorLayout.LayoutParams(fabSize, fabSize);
    p.rightMargin = p.leftMargin = p.bottomMargin = p.topMargin = margin;
    p.anchorGravity = Gravity.BOTTOM | Gravity.END;
    p.setAnchorId(R.id.appbar);
    fab.setLayoutParams(p);
    // Start from 1 pixel
    fab.setAlpha(0f);
    fab.setScaleX(0f);
    fab.setScaleY(0f);
    binding.coordinatorLayout.addView(fab);
    fab.animate()
       .alpha(1f)
       .scaleX(1f)
       .scaleY(1f)
       .setDuration(200)
       .setInterpolator(new FastOutLinearInInterpolator());

    fab.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            hidePlayButton(fab);
            // do action
        }
    });
}
0
Lisa Wray

Si vous utilisez ce code:

boolean mFabShouldBeShown;
FloatingActionButton.OnVisibilityChangedListener fabListener = new FloatingActionButton.OnVisibilityChangedListener() {
        @Override
        public void onShown(FloatingActionButton fab) {
            super.onShown(fab);
            if(!mFabShouldBeShown){
                fab.hide();
            }
        }

        @Override
        public void onHidden(FloatingActionButton fab) {
            super.onHidden(fab);
            if(mFabShouldBeShown){
                fab.show();
            }
        }
};

public void methodWhereFabIsHidden() {
    mFabShouldBeShown = false;
    mFloatingActionButton.hide(fabListener);
}

public void methodWhereFabIsShown() {
    mFabShouldBeShown = true;
    mFloatingActionButton.show(fabListener);
}
0
Cabezas

Si vous voulez cacher la fab, vous pouvez essayer ceci: Fab.hide ();

sinon essayez fab.show ();

prendre plaisir.

0
Jay

J'ai corrigé le problème show ()/hide () en plaçant le FAB dans ou hors de l'écran à l'aide des marges du modèle. Exemple:

CoordinatorLayout.LayoutParams p =
   new CoordinatorLayout.LayoutParams(
      CoordinatorLayout.LayoutParams.WRAP_CONTENT,
      CoordinatorLayout.LayoutParams.WRAP_CONTENT);

p.gravity = Gravity.BOTTOM | Gravity.LEFT;
int fabMargin = (int)res.getDimension(R.dimen.fab_margin);

if( enabled ) {
   p.setMargins(fabMargin,0,0,fabMargin);
}
else {
   p.setMargins(-200,0,0,fabMargin);
}
mFab.setLayoutParams(p);
0
Yossi Liron

Code simple:

   public static void setVisibilityFab(FloatingActionButton fab, int visibility)
  {

        CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
        p.setAnchorId(View.NO_ID);
        fab.setLayoutParams(p);
        if(visibility==View.GONE || visibility==View.INVISIBLE)
            fab.setVisibility(View.GONE);
        else
            fab.setVisibility(View.VISIBLE);
    }
0
Ahmad Aghazadeh

Je sais que votre réponse porte sur la façon de le faire fonctionner pour gone visibilité, mais si vous utilisez invisible à la place, vous ne vous inquiétez pas de cela et consomme moins de code.

0
Caipivara

voici une solution simple

private var fabAnchorId: Int = View.NO_ID
private val fabParams: CoordinatorLayout.LayoutParams
        get() = (fab.layoutParams as CoordinatorLayout.LayoutParams)

fun showFab() {
    fabParams.anchorId = fabAnchorId
    fabParams.gravity = Gravity.NO_GRAVITY
    fab.show()
}

fun hideFab() {
    fabParams.anchorId = View.NO_ID
    fabParams.gravity = Gravity.END.or(Gravity.BOTTOM)
    fab.hide()
}

avant de montrer/cacher nous devons changer l'ancre et la gravité

0
przebar