简体   繁体   English

如果在 CoordinatorLayout 中设置了 anchorView,则浮动操作按钮不会随 Snackbar 一起浮动

[英]Floating Action Button Not Floating With Snackbar If anchorView set within CoordinatorLayout

When I set snackbar.anchorView = adContainer my FAB doesn't float.当我设置 snackbar.anchorView = adContainer 时,我的 FAB 不会浮动。

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

        }
        snackbar.show()

If I don't set an anchor view it floats ok.如果我不设置锚视图,它会浮动。

Question - how can I get the FAB to float up and down if I set the snackbar anchor view to be adContainer?问题 - 如果我将 snackbar 锚点视图设置为 adContainer,如何让 FAB 上下浮动?

snackbar with anchorview set带有 anchorview 集的小吃店

snackbar without anchorview没有锚视图的小吃店

My XML file-我的 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>

Thanks to @Zain for his answer.感谢@Zain 的回答。 With my code below I had managed to get the FAB working except there was no bottom margin.使用下面的代码,我设法使 FAB 正常工作,但没有底边距。 With Zains solution there was a bottom margin.对于 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()

I can't write simple comment sorry about that.我不能写简单的评论对不起。 Can you try to add in your Manifest file below which activity you try to do that android:windowSoftInputMode="adjustResize"您可以尝试在您的清单文件中添加您尝试执行的活动android:windowSoftInputMode="adjustResize"

You need to create a custom CoordinatorLayout.Behavior class with FloatingActionButton as the view type that this Behavior operates on您需要创建一个自定义CoordinatorLayout.Behavior class 与FloatingActionButton作为此行为操作的视图类型

The credits of below custom java class back to this Repo .以下自定义 java class 的学分返回到此回购 I just converted it into Kotlin.我刚刚将它转换为 Kotlin。

You can use either the Kotlin or Java versions.您可以使用 Kotlin 或 Java 版本。

Kotlin: Kotlin:

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

Then use this class in your fab app:layout_behavior attribute to make the CoordinatorLayout functions with the needed behavior然后在您的 fab app:layout_behavior属性中使用此 class 以使CoordinatorLayout功能具有所需的行为

The full layout:完整的布局:

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

And of course you need to keep snackbar.anchorView = adContainer as-is当然你需要保持snackbar.anchorView = adContainer原样

Preview预习

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM