我来这里是为了加我的 2 美分,因为这是我在谷歌搜索那个确切的标题后登陆的地方。
我希望帮助像我这样的人还为时不晚。
首先,解决方案来自这里,所以不是我的。我刚试过,效果很好。所以我想我在一篇文章中与您分享,而不是让您从那里挖掘代码。
该解决方案使用com.android.support:design:25.3.1
库,因此请务必将其添加到 build.gradle 并且它需要 API 21 及更高版本。
坏消息是它由几个小的移动部分组成:5 个动画师、5 个可绘制对象以及图标和布局,当然还有代码,好消息是它可以正常工作,高度可定制且不需要MainActivity 之外的任何编码。
一些注意事项:
- 大晶圆厂的图像在更多和负号之间变形,并在点击时旋转。
- 按钮可以有文本,前提是您将文本和每个小 fab 都放在 LineaLayout 中,并将按钮 id 移动到 LinearLayout 以便它获得动画而不是 fab,但它需要代码在必要时隐藏和显示文本。
这是结果:
所以,成分:
- 可绘制对象(res/drawable/)。
animated_minus.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:height="24dp">
<group android:name="plus_group" android:pivotX="12" android:pivotY="12">
<path
android:name="plus_path"
android:strokeColor="@android:color/white"
android:strokeWidth="3"
android:pathData="M12,0L12,24M0,12,L24,12" />
</group>
</vector>
animated_plus.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/plus">
<target
android:animation="@animator/rotate_clockwise"
android:name="plus_group" />
<target
android:animation="@animator/plus_to_minus"
android:name="plus_path" />
</animated-vector>
fab_background.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent" />
</shape>
</item>
</ripple>
minus.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:height="24dp">
<group android:name="plus_group" android:pivotX="12" android:pivotY="12">
<path
android:name="plus_path"
android:strokeColor="@android:color/white"
android:strokeWidth="3"
android:pathData="M12,12L12,12M0,12,L24,12" />
</group>
</vector>
plus.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
android:height="24dp">
<group android:name="plus_group" android:pivotX="12" android:pivotY="12">
<path
android:name="plus_path"
android:strokeColor="@android:color/white"
android:strokeWidth="3"
android:pathData="M12,0L12,24M0,12,L24,12" />
</group>
</vector>
- 动画师(res/animator/)。
fab_state_list_animator.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:state_enabled="true">
<set>
<objectAnimator
android:propertyName="translationZ"
android:duration="100"
android:valueTo="3dp"
android:valueType="floatType" />
<objectAnimator
android:propertyName="elevation"
android:duration="0"
android:valueTo="5dp"
android:valueType="floatType" />
</set>
</item>
<!-- base state -->
<item android:state_enabled="true">
<set>
<objectAnimator
android:propertyName="translationZ"
android:duration="100"
android:valueTo="0"
android:startDelay="100"
android:valueType="floatType" />
<objectAnimator
android:propertyName="elevation"
android:duration="0"
android:valueTo="5dp"
android:valueType="floatType" />
</set>
</item>
<item>
<set>
<objectAnimator
android:propertyName="translationZ"
android:duration="0"
android:valueTo="0"
android:valueType="floatType" />
<objectAnimator
android:propertyName="elevation"
android:duration="0"
android:valueTo="0"
android:valueType="floatType" />
</set>
</item>
</selector>
minus_to_plus.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="pathData"
android:valueFrom="M12,0L12,24M12,12,L12,12"
android:valueTo="M12,0L12,24M0,12,L24,12"
android:valueType="pathType"
android:duration="@android:integer/config_mediumAnimTime" />
plus_to_minus.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="pathData"
android:valueFrom="M12,0L12,24M0,12,L24,12"
android:valueTo="M12,0L12,24M12,12,L12,12"
android:valueType="pathType"
android:duration="@android:integer/config_mediumAnimTime" />
rotate_anticlockwise.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="rotation"
android:valueFrom="90"
android:valueTo="0"
android:valueType="floatType"
android:duration="@android:integer/config_mediumAnimTime" />
rotate_clockwise.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="90"
android:valueType="floatType"
android:duration="@android:integer/config_mediumAnimTime" />
- 布局。(资源/布局/)
fab.xml
. 所有的晶圆厂都在这里宣布。android:src
在前 3 上替换为您自己的图标ImageButtons
。
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="@+id/fab_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:clipChildren="false" >
<!-- Please note that the @id are defined the first time they're referenced from top to bottom -->
<ImageButton
android:id="@+id/fab_action_3"
style="@style/FloatingActionButton.Mini"
android:src="@drawable/ic_volume_up_white_24dp"
android:layout_above="@+id/fab_action_2"
android:layout_alignEnd="@+id/fab"
android:contentDescription="@null"
android:backgroundTint="@color/sa_gray"
android:width="24dp"
android:height="24dp"
android:onClick="fabAction3" />
<ImageButton
android:id="@id/fab_action_2"
style="@style/FloatingActionButton.Mini"
android:src="@drawable/ic_credit_card_white_24dp"
android:layout_above="@+id/fab_action_1"
android:layout_alignEnd="@id/fab"
android:contentDescription="@null"
android:backgroundTint="@color/sa_gray"
android:width="24dp"
android:height="24dp"
android:onClick="fabAction2" />
<ImageButton
android:id="@id/fab_action_1"
style="@style/FloatingActionButton.Mini"
android:src="@drawable/ic_add_shopping_cart_white_24dp"
android:layout_above="@id/fab"
android:layout_alignEnd="@id/fab"
android:contentDescription="@null"
android:backgroundTint="@color/sa_gray"
android:width="24dp"
android:height="24dp"
android:onClick="fabAction1" />
<ImageButton
android:id="@id/fab"
style="@style/FloatingActionButton"
android:src="@mipmap/ic_add_w"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:contentDescription="@null"
android:visibility="visible"
android:layout_marginTop="8dp" />
</RelativeLayout>
</merge>
最后。
- 代码(java//MainActivity.java)
a) 一些声明:
private static final String TAG = "Floating Action Button";
private static final String TRANSLATION_Y = "translationY";
private ImageButton fab;
private boolean expanded = false;
private View fabAction1;
private View fabAction2;
private View fabAction3;
private float offset1;
private float offset2;
private float offset3;
b) 删除MainActivity
's上通常的 fab 代码onCreate
:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
并将其替换为:
final ViewGroup fabContainer = (ViewGroup) findViewById(R.id.fab_container);
fab = (ImageButton) findViewById(R.id.fab);
fabAction1 = findViewById(R.id.fab_action_1);
// insert onClickListener here
fabAction2 = findViewById(R.id.fab_action_2);
// insert onClickListener here
fabAction3 = findViewById(R.id.fab_action_3);
// insert onClickListener here
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
expanded = !expanded;
if (expanded) {
expandFab();
} else {
collapseFab();
}
}
});
fabContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
fabContainer.getViewTreeObserver().removeOnPreDrawListener(this);
offset1 = fab.getY() - fabAction1.getY();
fabAction1.setTranslationY(offset1);
offset2 = fab.getY() - fabAction2.getY();
fabAction2.setTranslationY(offset2);
offset3 = fab.getY() - fabAction3.getY();
fabAction3.setTranslationY(offset3);
return true;
}
});
c) 增加支持功能MainActivity
(主要是动画代码和3个小工厂的onClick
方法):
private void collapseFab() {
fab.setImageResource(R.drawable.animated_minus);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(createCollapseAnimator(fabAction1, offset1),
createCollapseAnimator(fabAction2, offset2),
createCollapseAnimator(fabAction3, offset3));
animatorSet.start();
animateFab();
}
private void expandFab() {
fab.setImageResource(R.drawable.animated_plus);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(createExpandAnimator(fabAction1, offset1),
createExpandAnimator(fabAction2, offset2),
createExpandAnimator(fabAction3, offset3));
animatorSet.start();
animateFab();
}
private Animator createCollapseAnimator(View view, float offset) {
return ObjectAnimator.ofFloat(view, TRANSLATION_Y, 0, offset)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
private Animator createExpandAnimator(View view, float offset) {
return ObjectAnimator.ofFloat(view, TRANSLATION_Y, offset, 0)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
private void animateFab() {
Drawable drawable = fab.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
}
public void fabAction1(View view) {
Log.d(TAG, "Action 1");
Toast.makeText(this, "Go shopping!", Toast.LENGTH_SHORT).show();
}
public void fabAction2(View view) {
Log.d(TAG, "Action 2");
Toast.makeText(this, "Gimme money!", Toast.LENGTH_SHORT).show();
}
public void fabAction3(View view) {
Log.d(TAG, "Action 3");
Toast.makeText(this, "Turn it up!", Toast.LENGTH_SHORT).show();
}
d) 参考 fab.xml 布局res/layout/activity_main.xml
删除 fab 声明:
<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" />
用。。。来代替:
<include layout="@layout/fab" />
最后的笔记:
- 随意废弃
onClick
晶圆厂的代码并将其替换为
onClickListener
. 那些应该放在评论说的地方
// insert onClickListener here
。只需记住删除
文件onClick
中每个 fab 的属性
并fab.xml
去掉MainActivity
(fabAction1
和) 中的最后 3 个函数。fabAction2
fabAction3
- 大多数度量、维度等。我将它们直接放在代码中以避免包含更多文件。
- 代码没有以任何方式进行优化。
我希望这对某人有所帮助,并对文字墙感到抱歉。