【问题标题】:FloatingActionButton doesn't hideFloatingActionButton 不隐藏
【发布时间】:2015-09-25 00:33:14
【问题描述】:

我正在尝试以编程方式隐藏我的 FloatingActionButton fabLocation

fabLocation.setVisibility(View.GONE)

但它不起作用。

如果我在我的 XML 布局中添加 android:visibility="gone"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" />

【问题讨论】:

    标签: android material-design android-design-library floating-action-button


    【解决方案1】:

    这是由于app:layout_anchor 属性。在更改可见性之前,您必须摆脱锚:

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

    【讨论】:

    • 如果我们使用 fab.hide() 而不是 setVisibility(View.GONE) 怎么办?因为现在您的示例将在屏幕左上角显示 fab 动画(变小)一秒钟,然后它就会消失,这是不受欢迎的行为,理想情况下您希望它就地隐藏。
    • @Linxy 有同样的问题
    • 对于像我这样的其他人。动画也有同样的问题。解决方案是将 fab.width 和 fab.height 设置为零,如本问题所述。 stackoverflow.com/questions/32732932/…
    • 我的 FAB 在没有 app:layout_anchor 的相对布局内,并且还以编程方式和通过 XML 尝试了 setVisiblity。有什么解决办法吗?
    • 它对我不起作用,所以我只设置了 fab 的“x”。晶圆厂.x = -500f;和 fab.x = oldPos;把它带回来
    【解决方案2】:

    锚定到 AppBarLayouts 的 FloatingActionButtons 具有特殊的关系,它们的可见性由 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);
    }
    

    【讨论】:

    • fab.getBehavior() 方法未找到?
    • 它有效。从 CoordinatorLayout.LayoutParams 获取行为
    • 使用behavior_autoHide 是不够的。默认情况下,它是使用默认构造函数创建的。要使此属性起作用,您必须将 layout_behavior 显式指定为 com.google.android.material.floatingactionbutton.FloatingActionButton$Behavior
    【解决方案3】:

    隐藏和显示浮动操作按钮的最简单方法是在您的活动中调用它。这也会自动正确地为您的 FAB 设置动画。

    隐藏:

    nameOfYourFAB.Hide();
    

    显示:

    nameOfYourFAB.Show();
    

    【讨论】:

    • 这在所有情况下都不起作用,例如涉及 CoordinatorLayout 中的 FAB
    【解决方案4】:

    我对发布的任何解决方案都不完全满意。有些只在部分时间工作,而另一些只为fab.setVisibility() 工作。虽然我知道这在技术上是最初的问题所问的,但一些回复表示有兴趣使用fab.hide(),并且弄乱布局参数并不能完全解决问题的根源。

    正如@ChrisBanes 所指出的,FloatingActionButton.BehaviorAppBarLayout 相关联是导致问题的原因。因此,正如他的回答一样,您必须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);
        }
    }
    

    【讨论】:

      【解决方案5】:
      FloatingActionButton layers = (FloatingActionButton) findViewById(R.id.layers);
      layers.hide();
      

      它适用于我,setVisibility 不适用于 FloatingActionButton,因为它属于另一个没有 setVisibility 方法的 viewGroup

      【讨论】:

      • 它适用于我,setVisibility 不适用于 FloatingActionButton,因为它属于另一个没有 setVisibility 方法的 viewGroup。
      【解决方案6】:

      如果你想显示隐藏的 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);
      

      【讨论】:

      • 谢谢!对返回按钮很有用。
      【解决方案7】:

      在一些答案之后,我为我的问题找到了解决方案(当工厂被隐藏时,它也可以处理行动!)。

      首先我建议您将.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();
          }
      

      【讨论】:

      • 哦,Android,为什么这么复杂?谢谢
      【解决方案8】:

      真正解决您的问题的方法是将默认FloatingActionButton.Behavior 子类化为在其构造函数中调用setAutoHide(false),这样您就可以自己控制它。

      请注意,我在下面讨论的是底部工作表,但对于所有锚定的浮动操作按钮来说,这都是完全相同的问题,并且它确实响应了问题并且应该按预期解决问题。 p>

      或者,您可以从自定义 Behavior 中覆盖 boolean onDependentViewChanged(…) 方法,复制 FloatingActionButton.Behavior 类中存在的 isBottomSheet(…) 静态方法,并且仅调用并返回不是底部工作表的超级方法的值.

      您可以通过这种方式进一步自定义默认行为,或者直接扩展 vanilla 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);
          }
      }
      

      我以这种方式将它应用到我的 xml 中的 FAB:

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

      【讨论】:

        【解决方案9】:

        这是一个简单的解决方案

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

        在显示/隐藏之前,我们必须改变锚点和重力

        【讨论】:

          【解决方案10】:

          这些其他解决方案都没有 100% 帮助我。我需要重复的动画显示和隐藏(如FAB.show()hide()),同时在可见时锚定到应用栏。

          我每次展示 FAB 时都会创建新的 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
                  }
              });
          }
          

          【讨论】:

            【解决方案11】:

            简单代码:

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

            【讨论】:

              【解决方案12】:

              我知道您的回答是关于如何使其适用于 gone 可见性,但如果您使用 invisible 代替,您将不必担心这一点并且代码更少。

              【讨论】:

                【解决方案13】:

                我通过使用布局边距将 FAB 放置在屏幕内或屏幕外来解决 show()/hide() 的缺点。示例:

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

                【讨论】:

                  【解决方案14】:

                  我用这个代码:

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

                  【讨论】:

                    【解决方案15】:

                    如果你想隐藏工厂,你可以试试这个: fab.hide();

                    再试试 fab.show();

                    享受吧。

                    【讨论】:

                      【解决方案16】:

                      隐藏浮动按钮

                      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;
                      

                      【讨论】:

                        【解决方案17】:

                        你可以这样做:

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

                        这与View.Gone 的行为相似

                        【讨论】:

                          猜你喜欢
                          • 2018-01-19
                          • 2021-02-03
                          • 1970-01-01
                          • 2016-06-03
                          • 2015-10-15
                          • 2016-01-17
                          • 2021-06-17
                          • 2019-07-05
                          • 2016-05-13
                          相关资源
                          最近更新 更多