既然Android设计支持库已经推出,有没有人知道如何用它实现扩展的Fab菜单,比如Inbox App上的fab?
应该是这样的:
答案 0 :(得分:136)
目前,设计库中没有提供小部件。唯一的方法快速,轻松是使用第三方库。
显然,使用设计库也可以做到这一点,但这将是一项巨大的工作,需要大量的时间。我已经提到了一些有用的库,可以帮助你实现这一目标。
我正在使用第四个。
答案 1 :(得分:131)
回答这个问题有点晚了,但我有一个更好的方法来实现动画FAB菜单而不使用任何库或为动画编写巨大的xml代码。希望这对将来需要一种简单方法来实现这一点的人有所帮助。
因此,使用animate()。translationY()函数非常简单,您可以使用我的下面的代码check complete code in github向上或向下设置FAB的动画。
首先在同一个地方定义所有FAB,使它们相互重叠,记住最重要的是FAB应该是你要点击并显示其他的。例如:
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab3"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_btn_speak_now" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_menu_camera" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_dialog_map" />
<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"
app:srcCompat="@android:drawable/ic_dialog_email" />
现在在您的java类中,只需定义所有FAB并执行如下所示的点击:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab1 = (FloatingActionButton) findViewById(R.id.fab1);
fab2 = (FloatingActionButton) findViewById(R.id.fab2);
fab3 = (FloatingActionButton) findViewById(R.id.fab3);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!isFABOpen){
showFABMenu();
}else{
closeFABMenu();
}
}
});
现在使用animation()。translationY()来动画你的FAB,我更喜欢你在DP中使用这个方法的属性,因为只使用int会影响更高分辨率或更低分辨率的显示兼容性。如下图所示:
private void showFABMenu(){
isFABOpen=true;
fab1.animate().translationY(-getResources().getDimension(R.dimen.standard_55));
fab2.animate().translationY(-getResources().getDimension(R.dimen.standard_105));
fab3.animate().translationY(-getResources().getDimension(R.dimen.standard_155));
}
private void closeFABMenu(){
isFABOpen=false;
fab1.animate().translationY(0);
fab2.animate().translationY(0);
fab3.animate().translationY(0);
}
现在在res-&gt; values-&gt; dimens.xml中定义上面提到的维度,如下所示:
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
所有人都希望这个解决方案能够帮助将来寻找简单解决方案的人们。
EDITED
如果你想在FAB上添加标签,那么只需要一个水平的LinearLayout,然后将带有textview的FAB作为标签,如果发现任何问题,可以设置布局动画,你可以在github中检查我的示例代码,我已经handelled该示例代码中的所有向后兼容性问题。 check my sample code for FABMenu in Github
关闭Backpress上的FAB,覆盖onBackPress(),如下图所示:
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
屏幕截图也有FAB的标题,因为我是从我的sample app present ingithub
取的答案 2 :(得分:28)
首先在Activity布局xml文件中创建菜单布局。对于例如一个 水平方向的线性布局,包括TextView for 然后在TextView旁边标记一个浮动操作按钮。
根据您的需要和编号创建菜单布局。
创建基本浮动操作按钮及其 点击该按钮可更改菜单布局的可见性。
请查看以下代码以获取参考信息以及从github
查看我的项目的更多信息<android.support.constraint.ConstraintLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.fabmenu.MainActivity">
<android.support.design.widget.FloatingActionButton
android:id="@+id/baseFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:onClick="@{FabHandler::onBaseFabClick}"
android:tint="@android:color/white"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="@+id/activity_main"
app:layout_constraintRight_toRightOf="@+id/activity_main"
app:srcCompat="@drawable/ic_add_black_24dp" />
<LinearLayout
android:id="@+id/shareLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/createLayout"
app:layout_constraintLeft_toLeftOf="@+id/createLayout"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/shareLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Share"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/shareFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onShareFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_share_black_24dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/createLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/baseFloatingActionButton"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/createLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Create"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/createFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onCreateFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_create_black_24dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
这些是动画 -
打开FAB菜单的动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="0"
android:fromYScale="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
关闭FAB菜单的动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="1"
android:fromYScale="1"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>
然后在我的活动中,我只是使用上面的动画来显示和隐藏FAB菜单:
显示Fab菜单:
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
关闭Fab菜单:
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
这是Activity类 -
package com.app.fabmenu;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
import com.app.fabmenu.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Animation fabOpenAnimation;
private Animation fabCloseAnimation;
private boolean isFabMenuOpen = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setFabHandler(new FabHandler());
getAnimations();
}
private void getAnimations() {
fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
}
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
public class FabHandler {
public void onBaseFabClick(View view) {
if (isFabMenuOpen)
collapseFabMenu();
else
expandFabMenu();
}
public void onCreateFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Create FAB tapped", Snackbar.LENGTH_SHORT).show();
}
public void onShareFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Share FAB tapped", Snackbar.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
if (isFabMenuOpen)
collapseFabMenu();
else
super.onBackPressed();
}
}
以下是截图
答案 3 :(得分:13)
答案 4 :(得分:6)
当我尝试创建一个类似于收件箱浮动动作按钮的东西时,我考虑创建自己的自定义组件。
这将是具有固定高度(包含扩展菜单)的简单框架布局,其中包含FAB按钮,另外3个放置在FAB下方。当你点击FAB时,你只需简单地设置其他按钮的动画就可以从FAB下面进行翻译。
有一些图书馆可以做到这一点(例如https://github.com/futuresimple/android-floating-action-button),但如果你自己创建它会更有趣:)
答案 5 :(得分:6)
您可以使用FloatingActionMenu库或click here逐步教程。教程的输出:
答案 6 :(得分:3)
万一有人还在寻找该功能:我制作了一个具有此功能以及更多功能的Android库,称为ExpandableFab(https://github.com/nambicompany/expandable-fab)。
“材料设计”规范将此功能称为'Speed Dial',ExpandableFab将其与许多其他功能一起实现。
几乎所有内容都是可自定义的(颜色,文本,大小,位置,边距,动画等)和可选的(不需要Overlay,FabOptions,Label或图标等)。可以通过XML布局或以编程方式访问或设置每个属性-无论您喜欢哪种。
在Kotlin中100%编写,但随附完整的JavaDoc和KDoc(已公开的API有据可查)。还附带一个示例应用程序,因此您可以看到0编码的不同用例。
Github:https://github.com/nambicompany/expandable-fab
图书馆网站(带有完整文档的链接):https://nambicompany.github.io/expandable-fab/
答案 7 :(得分:2)
答案 8 :(得分:0)