两个相邻的浮动操作按钮

Two floating action buttons next to each other

material 设计文档有一个 Google 地图示例,显示两个浮动操作按钮彼此相邻(实际上,一个在另一个上方)。

这是怎么做到的?我在协调器布局中有两个 FAB,但它们最终叠放在一起,所以您只能看到一个按钮。

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Use ThemeOverlay to make the toolbar and tablayout text
             white -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/abl_top"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/img_photo"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:background="#C5C5C5"/>
        <EditText
            android:id="@+id/text_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/img_baby"
            android:layout_alignParentStart="true"
            android:layout_alignParentLeft="true"
            android:hint="Name"
            android:drawableLeft="@drawable/ic_account"
            android:drawablePadding="20dp"
            android:textAppearance="?android:attr/textAppearanceSmall" />
        <TextView
            android:id="@+id/text_dob"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/text_name"
            android:layout_alignParentStart="true"
            android:layout_alignParentLeft="true"
            android:hint="Date of birth"
            android:drawableLeft="@drawable/ic_cake"
            android:drawablePadding="20dp"
            style="@android:style/Widget.Holo.Spinner"/>

    </LinearLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_camera"
        android:clickable="true"
        app:fabSize="mini"
        app:layout_anchor="@id/img_photo"
        app:layout_anchorGravity="bottom|right|end"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_gallery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_image"
        android:clickable="true"
        app:fabSize="mini"
        app:layout_anchor="@id/img_photo"
        app:layout_anchorGravity="bottom|right|end"/>

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

它是布局引力和锚点引力的结合,加上(锚定项目的)边距可以使它工作,看看下面的 xml 我已经成功使用:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    android:src="@android:drawable/ic_dialog_info" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="top|end"
    android:layout_marginBottom="0dp"
    android:layout_marginEnd="0dp"
    android:layout_marginLeft="0dp"
    android:layout_marginRight="0dp"
    android:layout_marginStart="0dp"
    android:layout_marginTop="0dp"
    android:src="@android:drawable/ic_media_play"
    app:layout_anchor="@id/fab"
    app:layout_anchorGravity="top" />

中间有100dp space的两个浮动操作按钮如下:

<android.support.design.widget.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:layout_gravity="top|end"
    android:layout_marginBottom="100dp"
    android:src="@android:drawable/ic_input_add"
    app:layout_anchor="@id/fab"
    app:layout_anchorGravity="top" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    android:src="@android:drawable/ic_delete />

这个答案 有一个主要问题:我们无法在两个按钮之间设置任何边距。他们粘在一起。

似乎在设计支持库 v23.3.0 的当前状态下,我们无法在协调器布局中拥有多个行为正确的浮动操作按钮。但是在规范 https://www.google.com/design/spec/components/buttons-floating-action-button.html#buttons-floating-action-button-transitions 中描述了此功能,因此我们可以期待它在未来。

至于我发现了一个解决方法:

当您查看 google 地图 android 应用程序时,您会注意到第一个(蓝色)浮动操作按钮随底部浮动 sheet,而第二个(我的位置)按钮不是。因此,对于第二个按钮,创建一个跨越整个布局的环绕相对布局。将它放在底部 sheet 布局之上:

<RelativeLayout
    android:id="@+id/wrapper"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/secondButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

</RelativeLayout>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/firstButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="15dp"
    app:layout_anchor="@id/bottomSheet"
    app:layout_anchorGravity="top|right|end"/>

这将完全模仿 google 地图的浮动操作按钮。此解决方案的一个缺点是您必须设置包装器的底部边距以将按钮定位在第一个按钮上方。您可以在布局中或以编程方式执行此操作:

((CoordinatorLayout.LayoutParams) wrapper.getLayoutParams()).setMargins(0, 0, 0, bottomMargin);

这是我的解决方案,只是在两个fab之间放一个不可见的FAB,并且与CoordinatorLayout配合得很好。

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    android:src="@drawable/ic_check" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_invisible"
    android:layout_width="@dimen/fab_margin"
    android:layout_height="@dimen/fab_margin"
    android:layout_gravity="top|end"
    android:layout_margin="@dimen/fab_margin"
    android:visibility="invisible"
    app:layout_anchor="@id/fab"
    app:layout_anchorGravity="top" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_follow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="top|end"
    android:layout_margin="@dimen/fab_margin"
    android:src="@drawable/ic_gps_fixed_follow"
    app:backgroundTint="@android:color/white"
    app:layout_anchor="@id/fab_invisible"
    app:layout_anchorGravity="top" />

No Snackbar

With Snackbar

这对我有用 - FAB 嵌入在相对布局中:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.github.openeet.openeet.SaleDetailActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/appbar_padding_top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/AppTheme.PopupOverlay">

        </android.support.v7.widget.Toolbar>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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

    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_margin="@dimen/fab_margin"
        android:layout_gravity="end|bottom" >


        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab_share"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|bottom"
            android:src="@android:drawable/ic_menu_share"
            android:layout_alignParentBottom="true"
            android:layout_alignLeft="@+id/fab_print"
            android:layout_alignStart="@+id/fab_print" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab_print"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|bottom"
            android:src="@android:drawable/ic_media_next"
            android:layout_above="@+id/fab_share"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_marginBottom="46dp" />

    </RelativeLayout>

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

尝试使用这个app:useCompatPadding="true"

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fabBottom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="@android:color/white"
    android:src="@mipmap/ic_search"
    app:fabSize="normal"
    android:scaleType="center"
    app:layout_anchor="@+id/bottomSheet"
    app:layout_anchorGravity="top|end"
    app:useCompatPadding="true"/>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fabTop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="@color/accent"
    android:src="@mipmap/ic_location_on"
    app:backgroundTint="@android:color/white"
    app:fabSize="normal"
    android:scaleType="center"
    android:layout_gravity="top|end"
    app:layout_anchor="@+id/fabSearch"
    app:layout_anchorGravity="top|end"
    android:layout_margin="12dp"/>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_camera"
        android:layout_gravity="bottom|right"
        android:layout_margin="16dp"
        app:fabSize="normal" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_image"
        app:useCompatPadding="true"
        app:layout_anchor="@id/fab_camera"
        app:layout_anchorGravity="top|center"
        android:layout_gravity="top|center"
        app:fabSize="normal" />

三个按钮一个在另一个上面:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_zoom_out"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end|bottom"
    android:layout_margin="@dimen/fab_margin"
    app:srcCompat="@drawable/ic_fab_zoom_out"
    app:elevation="0dp"
    app:useCompatPadding="true"
    />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_zoom_in"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end|top"
    app:srcCompat="@drawable/ic_fab_zoom_in"
    app:elevation="0dp"
    app:useCompatPadding="true"
    app:layout_anchor="@id/fab_zoom_out"
    app:layout_anchorGravity="start"
    />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_reset_orientation"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end|top"
    android:visibility="gone"
    app:srcCompat="@drawable/ic_fab_reset_orientation"
    app:elevation="0dp"
    app:useCompatPadding="true"
    app:layout_anchor="@id/fab_zoom_in"
    app:layout_anchorGravity="start"
    />
<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_scrolling"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/big_activity_fab_margin"
    android:src="@drawable/ic_share_white_24dp"
    app:layout_anchor="@id/app_bar_scrolling"
    app:layout_anchorGravity="bottom|end" />
<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab_scrolling2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="65dp"
    android:src="@drawable/ic_share_white_24dp"
    app:layout_anchor="@id/app_bar_scrolling"
    app:layout_anchorGravity="bottom|end" />

这对我有用。关键代码是 android:layout_margin="65dp"

我不敢相信没有人发布正确答案。

将按钮包裹在 ViewGroup 中并应用 dodgeInsetEdges 布局 参数,以便按钮与底部 sheet 一起向上移动。对于以上用途 在这种情况下,我们可以使用 LinearLayout 和 XML 属性 app:layout_dodgeInsetEdges="bottom".

请注意,我们可以将此应用于 任何 视图 CoordinatorLayout

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" ... >

    <!-- We can use any ViewGroup here. LinearLayout is the
         obvious choice for the questioner's use case. -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:orientation="vertical"
        app:layout_dodgeInsetEdges="bottom">

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/upperFab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/fab_margin"
            android:src="@drawable/upper_fab_icon" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/lowerFab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/lower_fab_icon" />

    </LinearLayout>

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

接受的答案(在撰写本文时)- 仅部分起作用,因为按钮粘在一起。

我也无法使用任何其他提供的答案。所以我找到了解决方法。

在 2 个 FAB 之间添加一个视图 像这样 -

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab2"
    android:src="@drawable/ic_delete_white_24dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="top|end"
    app:layout_anchor="@id/view"/>

<View
    android:id="@+id/view"
    android:layout_width="10dp"
    android:layout_height="10dp"
    android:layout_gravity="top|end"
    app:layout_anchor="@id/fab"
    />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:src="@drawable/ic_done_white_24dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:backgroundTint="@color/colorPrimary"
    app:layout_anchor="@id/bar2" />

一个非常简单的方法(对我有用!)就是将两个浮动按钮放置在其父级 bottom/end 的垂直线性布局中。

    <LinearLayout
    android:layout_gravity="bottom|end"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginEnd="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_menu_send" />
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_menu_send" />
</LinearLayout>

只需调整浮动按钮的 layout_margin 属性即可获得您想要的间距。

另一个建议

您还可以创建垂直或水平 LinearLayout,其中可能包含多个 FloatingActionButton,并将 LinearLayout 锚定到内部的特定目标视图你的 CoordinatorLayout.