如何在Android中实现此类Radial Floating Action Button
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

