FloatingActionButton не скрывает

Я пытаюсь программно скрыть свой FloatingActionButton fabLocation с помощью:

fabLocation.setVisibility(View.GONE)

Но это не работает.

Если я добавлю android:visibility="gone" в свой XML-макет, fabLocation будет скрыт, когда я запущу свою активность, но снова появится при прокрутке.

Вот мой макет:

<?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" />


person frenchdev20    schedule 07.07.2015    source источник


Ответы (17)


Это связано с атрибутом app:layout_anchor. Вы должны избавиться от привязки перед изменением видимости:

CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.setVisibility(View.GONE);
person natario    schedule 07.07.2015
comment
Как нам это сделать, если мы используем fab.hide() вместо setVisibility(View.GONE)? Поскольку прямо сейчас в вашем примере будет отображаться великолепная анимация (становящаяся меньше) в левом верхнем углу экрана на долю секунды, прежде чем она исчезнет, ​​что является нежелательным поведением, в идеале вы хотели бы, чтобы она сразу же скрылась. - person Linxy; 31.12.2015
comment
У @Linxy такая же проблема - person Konstantin Konopko; 16.03.2016
comment
Для других, таких как я. такая же проблема с анимацией. Решение состоит в том, чтобы установить fab.width и fab.height равными нулю, как указано в этом вопросе. stackoverflow.com/questions/32732932/ - person Gatunox; 29.03.2016
comment
@Linxy: если вам это все еще нужно, смотрите мой ответ ниже. Даже установка ширины и высоты 0 мне не помогла, в итоге я полностью удалил и добавил FAB из родительского макета. - person Lisa Wray; 14.04.2016
comment
мой FAB находится внутри относительного макета без приложения: layout_anchor, а также пробовал setVisiblity программно и через XML. Любое решение для этого? - person NAUSHAD; 19.01.2017
comment
У меня это не работает, поэтому я просто установил x из fab. фаб.х = -500f; и fab.x = oldPos; чтобы вернуть его - person Jayakrishnan; 08.04.2018

FloatingActionButtons, привязанные к AppBarLayouts, имеют особые отношения, когда их видимость контролируется положением прокрутки AppBarLayout.

Вы можете отключить это с помощью атрибута behavior_autoHide:

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

Вы также можете сделать это программно, если хотите:

ИЗМЕНИТЬ:

fab.getBehavior() был неправильным, используйте getBehavior() из его LayoutParams

CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
FloatingActionButton.Behavior behavior = (FloatingActionButton.Behavior) lp.getBehavior();
if (behavior != null) {
    behavior.setAutoHideEnabled(false);
} else {
    behavior = new FloatingActionButton.Behavior();
    behavior.setAutoHideEnabled(false);
    lp.setBehavior(behavior);
}
person Chris Banes    schedule 03.01.2017
comment
Метод fab.getBehavior() не найден? - person KittoKatto; 02.12.2017
comment
Оно работает. получить поведение от CoordinatorLayout.LayoutParams - person inhogo; 16.03.2018
comment
Использование behavior_autoHide недостаточно. По умолчанию он создается с помощью конструктора по умолчанию. Чтобы этот атрибут работал, вы должны явно указать layout_behavior для com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior - person wrozwad; 20.04.2020

Я не был полностью доволен ни одним из опубликованных решений. Некоторые работали только часть времени, а другие работали только fab.setVisibility(). Хотя я знаю, что технически это то, о чем задавался первоначальный вопрос, несколько ответов выразили заинтересованность в использовании fab.hide(), и возня с параметрами макета точно не доходит до сути проблемы.

Как указал @ChrisBanes, проблема связана с FloatingActionButton.Behavior и AppBarLayout. Итак, как и в случае с его ответом, вам нужно setAutoHideEnabled(false) отключить эту функцию. Но это решение не поможет, если вы действительно хотите, чтобы FloatingActionButton автоматически скрывалось и при вызове hide() вручную.

Итак, чтобы сделать это; Я просто отключаю функцию автоматического скрытия перед тем, как вручную скрыть Button, а затем снова включаю эту функцию после того, как вручную покажу 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);
    }
}
person Bryan    schedule 28.03.2017

Самый простой способ скрыть и отобразить плавающую кнопку действия — это вызвать ее в своей активности. Это также автоматически автоматически анимирует ваш FAB.

Скрывать:

nameOfYourFAB.Hide();

Шоу:

nameOfYourFAB.Show();
person Alex Carrington    schedule 14.06.2019
comment
это работает не во всех случаях, например, задействован FAB в CoordinatorLayout - person leeCoder; 12.11.2019

FloatingActionButton layers = (FloatingActionButton) findViewById(R.id.layers);
layers.hide();

Это работает для меня, setVisibility не работает для FloatingActionButton, так как принадлежит другому viewGroup, у которого нет метода setVisibility.

person Satendra Behre    schedule 22.11.2018
comment
Это работает для меня, setVisibility не работает для FloatingActionButton, поскольку он принадлежит другой группе просмотра, в которой нет метода setVisibility. - person Satendra Behre; 22.11.2018

Если вы хотите показать скрытый FAB

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

и

    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);
person Georgy Gobozov    schedule 27.11.2015
comment
Спасибо ! полезно, чтобы вернуть кнопку. - person Gopal Singh Sirvi; 11.12.2015

После нескольких ответов я нашел решение своей проблемы (также, когда fab скрыт, он может обрабатывать действия!).

Прежде всего, я предлагаю вам заменить .setVisibility(View.GONE) и .setVisibility(View.VISIBLE) на методы .show() и .hide(). Эти последние ручки также actionMode.

Вторая проблема для меня заключалась в том, что действие также обрабатывалось, когда фаб был скрыт, для решения этого я сделал это:

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();
    }
person ciccioska    schedule 14.07.2016
comment
О, Андроид, зачем так сложно? Спасибо - person Mrusful; 06.10.2018

Реальное решение вашей проблемы состоит в том, чтобы создать подкласс по умолчанию FloatingActionButton.Behavior для вызова setAutoHide(false) в своих конструкторах, чтобы вы могли управлять им самостоятельно.

Обратите внимание, что я говорю о нижних листах ниже, но это точно такая же проблема для всех привязанных плавающих кнопок действий, и она действительно отвечает на вопрос и должна решить проблему, как и ожидалось.

В качестве альтернативы вы можете переопределить метод boolean onDependentViewChanged(…) из своего пользовательского поведения, скопировать статический метод isBottomSheet(…), присутствующий в классе FloatingActionButton.Behavior, и вызывать и возвращать значение суперметода только в том случае, если он не является нижним листом.

Вы можете дополнительно настроить поведение по умолчанию таким образом или путем прямого расширения ванильного класса CoordinatorLayout.Behavior, и вы можете выбрать код для копирования и вставки из класса FloatingActionButton.Behavior, если это необходимо.

Вот код, который я использовал для управления видимостью 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);
    }
}

И я применил его к своему FAB в xml следующим образом:

<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>
person Louis CAD    schedule 23.09.2016

вот простое решение

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

перед показом/скрытием мы должны изменить привязку и гравитацию

person przebar    schedule 15.11.2016

Ни одно из этих других решений не помогло мне на 100%. Мне нужно было повторять анимированное отображение и скрытие (например, FAB.show() и hide()), когда они были привязаны к панели приложения, когда они были видны.

В итоге я создавал новый FAB каждый раз, когда показывал его, вручную вставлял и привязывал его, а также анимировал на основе реализации библиотеки поддержки. Это грубо, но это работает идеально.

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
        }
    });
}
person Lisa Wray    schedule 14.04.2016

Простой код:

   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);
    }
person Ahmad Aghazadeh    schedule 20.05.2016

Я знаю, что вы отвечаете на вопрос о том, как заставить его работать для видимости gone, но если вместо этого вы используете invisible, у вас не будет проблем с этим, и у вас будет меньше кода.

person Daniel Gomez Rico    schedule 18.07.2016

Я работал над недостатком show()/hide(), размещая FAB на экране или за его пределами, используя поля макета. пример:

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);
person Yossi Liron    schedule 24.07.2016

Я использую этот код:

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);
}
person Cabezas    schedule 21.09.2016

Если вы хотите скрыть фаб, вы можете попробовать это: fab.hide();

иначе попробуйте fab.show();

наслаждаться.

person Jay    schedule 21.10.2018

Чтобы скрыть плавающую кнопку

fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.hide;

и повторно показать

fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.show;
person Abanoub Hanna    schedule 07.03.2019

вы можете сделать это, используя это:

fab.setEnabled(false);
fab.setClickable(false);
fab.setAlpha(0.0f);

Это похоже на поведение View.Gone

person Khamidjon Khamidov    schedule 04.08.2020