【问题标题】:Floating Action Button Not Floating With Snackbar If anchorView set within CoordinatorLayout如果在 CoordinatorLayout 中设置了 anchorView,则浮动操作按钮不与 Snackbar 一起浮动
【发布时间】:2021-03-29 22:31:09
【问题描述】:

当我设置snackbar.anchorView = adContainer 时,我的FAB 不会浮动。

val snackbar = Snackbar.make(main_content, "Item Deleted", Snackbar.LENGTH_INDEFINITE)
        snackbar.anchorView = adContainer
        snackbar.setAction("Dismiss"){

        }
        snackbar.show()

如果我不设置锚点视图,它会浮动。

问题 - 如果我将小吃店锚视图设置为 adContainer,如何让 FAB 上下浮动?

snackbar with anchorview set

snackbar without anchorview

我的 XML 文件-

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/rootConstraintLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Show Snackbar"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/adContainer"
            android:layout_width="match_parent"
            android:layout_height="64dp"
            android:layout_marginStart="1dp"
            android:layout_marginTop="1dp"
            android:layout_marginEnd="1dp"
            android:layout_marginBottom="1dp"
            android:background="#F44336"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_marginBottom="96dp"
        android:layout_marginEnd="32dp"
        android:clickable="true"
        app:layout_anchorGravity="end|bottom"
        app:srcCompat="@android:drawable/ic_input_add"
        android:focusable="true" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

感谢@Zain 的回答。使用下面的代码,我设法让 FAB 工作,除了没有底部边距。使用 Zains 解决方案有一个底部边距。

val snackbar = Snackbar.make(main_content, "Item Deleted", Snackbar.LENGTH_INDEFINITE)
            snackbar.setAction("Dismiss"){

            }
            val snackbarView = snackbar.view
            val params = snackbarView.layoutParams as CoordinatorLayout.LayoutParams
            params.anchorId = R.id.adContainer
            params.bottomMargin = 16// this line didn't work
            params.gravity = Gravity.TOP
            params.anchorGravity = Gravity.TOP
            snackbarView.layoutParams = params
            snackbar.show()

【问题讨论】:

    标签: android android-layout floating-action-button android-coordinatorlayout android-snackbar


    【解决方案1】:

    您需要创建一个自定义的CoordinatorLayout.Behavior 类,并将FloatingActionButton 作为此行为操作的视图类型

    以下自定义 java 类的学分返回this Repo。我只是把它转换成 Kotlin。

    您可以使用 Kotlin 或 Java 版本。

    科特林:

    class BottomNavigationFABBehavior constructor(context: Context, attrs: AttributeSet?) :
        CoordinatorLayout.Behavior<FloatingActionButton>(context, attrs) {
    
      override fun layoutDependsOn(
          parent: CoordinatorLayout,
          child: FloatingActionButton,
          dependency: View
      ): Boolean {
            return dependency is SnackbarLayout
        }
    
        override fun onDependentViewRemoved(
            parent: CoordinatorLayout,
            child: FloatingActionButton,
            dependency: View
        ) {
            child.translationY = 0.0f
        }
    
        override fun onDependentViewChanged(
            parent: CoordinatorLayout,
            child: FloatingActionButton,
            dependency: View
        ): Boolean {
            return updateButton(child, dependency)
        }
    
        private fun updateButton(child: View, dependency: View): Boolean {
            return if (dependency is SnackbarLayout) {
                val oldTranslation = child.translationY
                val height = dependency.getHeight().toFloat()
                val newTranslation = dependency.getTranslationY() - height
                child.translationY = newTranslation
                oldTranslation != newTranslation
            } else {
                false
            }
        }
    }
    

    Java

    
    public final class BottomNavigationFABBehavior
            extends CoordinatorLayout.Behavior<FloatingActionButton> {
    
      public BottomNavigationFABBehavior(@Nullable Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
      }
    
      public boolean layoutDependsOn(
              @Nullable CoordinatorLayout parent,
              @NonNull FloatingActionButton child,
              @NonNull View dependency) {
        return dependency instanceof Snackbar.SnackbarLayout;
      }
    
      public void onDependentViewRemoved(
              @NonNull CoordinatorLayout parent,
              @NonNull FloatingActionButton child,
              @NonNull View dependency) {
        child.setTranslationY(0.0f);
      }
    
      public boolean onDependentViewChanged(
              @NonNull CoordinatorLayout parent,
              @NonNull FloatingActionButton child,
              @NonNull View dependency) {
        return this.updateButton(child, dependency);
      }
    
      private boolean updateButton(View child, View dependency) {
        if (dependency instanceof Snackbar.SnackbarLayout) {
          float oldTranslation = child.getTranslationY();
          float height = (float) dependency.getHeight();
          float newTranslation = dependency.getTranslationY() - height;
          child.setTranslationY(newTranslation);
          return oldTranslation != newTranslation;
        } else {
          return false;
        }
      }
    }
    

    然后在您的 fab app:layout_behavior 属性中使用此类以使 CoordinatorLayout 函数具有所需的行为

    完整版面:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.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">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/rootConstraintLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Show Snackbar"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/adContainer"
                android:layout_width="match_parent"
                android:layout_height="64dp"
                android:layout_marginStart="1dp"
                android:layout_marginTop="1dp"
                android:layout_marginEnd="1dp"
                android:layout_marginBottom="1dp"
                android:background="#F44336"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/floatingActionButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            app:fabSize="normal"
            app:layout_anchor="@id/adContainer"
            app:layout_anchorGravity="end|top"
            app:layout_behavior=".BottomNavigationFABBehavior2"
            app:srcCompat="@android:drawable/ic_input_add"
            app:useCompatPadding="true" />
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    当然你需要保持snackbar.anchorView = adContainer原样

    预览

    【讨论】:

      【解决方案2】:

      对此我不能写简单的评论抱歉。您可以尝试在您的清单文件中添加您尝试执行的活动吗 android:windowSoftInputMode="adjustResize"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 2016-07-26
        • 2015-12-13
        • 2015-10-23
        • 2016-01-09
        • 1970-01-01
        • 2015-11-08
        相关资源
        最近更新 更多