You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中实现此类Radial Floating Action Button

Implementing a Radial Floating Action Button in Android

Hey there! As someone new to Android design and Material Design, let's break down how to build that radial floating action button (FAB) you're aiming for, based on the web example you shared. We'll convert the web's CSS/JS logic into Android-compatible code using layouts and animations.

Step 1: Set Up the Layout

First, create a layout file (e.g., activity_main.xml) that includes your main FAB and three child action buttons. We'll use ConstraintLayout to position them neatly, with child buttons initially hidden or overlapping the main FAB.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <!-- Main FAB -->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/main_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_plus"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="24dp"
        app:backgroundTint="#ff4081"/>

    <!-- Child FABs (initially invisible) -->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_paper_plane"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_paper_plane"
        app:layout_constraintBottom_toBottomOf="@id/main_fab"
        app:layout_constraintEnd_toEndOf="@id/main_fab"
        android:visibility="invisible"
        app:backgroundTint="@android:color/transparent"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_home"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_home"
        app:layout_constraintBottom_toBottomOf="@id/main_fab"
        app:layout_constraintEnd_toEndOf="@id/main_fab"
        android:visibility="invisible"
        app:backgroundTint="@android:color/transparent"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_search"
        app:layout_constraintBottom_toBottomOf="@id/main_fab"
        app:layout_constraintEnd_toEndOf="@id/main_fab"
        android:visibility="invisible"
        app:backgroundTint="@android:color/transparent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Step 2: Create Animation Resources

Next, define the animations for expanding/collapsing child buttons and rotating the main FAB's icon.

Rotation Animation (Plus to Cross)

Create res/anim/rotate_plus.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="135"/>

Reverse Rotation Animation (Cross to Plus)

Create res/anim/rotate_back.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromDegrees="135"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="0"/>

Translate Animations for Child Buttons

Make animation files for each child to move to their radial positions. For example, res/anim/translate_paper_plane.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="-110dp"
    android:toYDelta="10dp"/>

Repeat this for the home and search buttons with adjusted toXDelta/toYDelta values matching the web example's positions.

Step 3: Implement Click Logic in Code

In your activity (e.g., MainActivity.kt), add a click listener to toggle expand/collapse state and trigger animations:

import android.os.Bundle
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton

class MainActivity : AppCompatActivity() {
    private var isExpanded = false

    private lateinit var mainFab: FloatingActionButton
    private lateinit var fabPaperPlane: FloatingActionButton
    private lateinit var fabHome: FloatingActionButton
    private lateinit var fabSearch: FloatingActionButton

    private lateinit var rotatePlus: Animation
    private lateinit var rotateBack: Animation
    private lateinit var translatePaperPlane: Animation
    private lateinit var translateHome: Animation
    private lateinit var translateSearch: Animation

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Initialize views
        mainFab = findViewById(R.id.main_fab)
        fabPaperPlane = findViewById(R.id.fab_paper_plane)
        fabHome = findViewById(R.id.fab_home)
        fabSearch = findViewById(R.id.fab_search)

        // Load animations
        rotatePlus = AnimationUtils.loadAnimation(this, R.anim.rotate_plus)
        rotateBack = AnimationUtils.loadAnimation(this, R.anim.rotate_back)
        translatePaperPlane = AnimationUtils.loadAnimation(this, R.anim.translate_paper_plane)
        translateHome = AnimationUtils.loadAnimation(this, R.anim.translate_home)
        translateSearch = AnimationUtils.loadAnimation(this, R.anim.translate_search)

        // Add delays to match the web example's staggered animation
        translateHome.startOffset = 100
        translateSearch.startOffset = 200

        // Main FAB click handler
        mainFab.setOnClickListener {
            if (!isExpanded) {
                // Switch to expanded state
                mainFab.startAnimation(rotatePlus)
                mainFab.setBackgroundTintList(resources.getColorStateList(R.color.dark_red))

                fabPaperPlane.visibility = android.view.View.VISIBLE
                fabHome.visibility = android.view.View.VISIBLE
                fabSearch.visibility = android.view.View.VISIBLE

                fabPaperPlane.startAnimation(translatePaperPlane)
                fabHome.startAnimation(translateHome)
                fabSearch.startAnimation(translateSearch)
            } else {
                // Switch to collapsed state
                mainFab.startAnimation(rotateBack)
                mainFab.setBackgroundTintList(resources.getColorStateList(R.color.red))

                fabPaperPlane.visibility = android.view.View.INVISIBLE
                fabHome.visibility = android.view.View.INVISIBLE
                fabSearch.visibility = android.view.View.INVISIBLE
            }
            isExpanded = !isExpanded
        }
    }
}

Add color values to res/values/colors.xml:

<resources>
    <color name="red">#ff4081</color>
    <color name="dark_red">#d81b60</color>
</resources>

Alternative: Use a Third-Party Library

If you don't want to build everything from scratch, try libraries like FloatingActionButtonMenu (available on Maven Central). It pre-packages radial expansion logic, so you can focus on customizing appearance and functionality without writing all the animation code yourself.


内容的提问来源于stack exchange,提问作者Manu Jindal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:25:51