我试图在我的应用中制作一个浮动操作按钮菜单。它看起来应该像Google日历应用中的FAB,这是材料设计指南中显示的一种有效的FAB:
在"浮动动作按钮改变焦点上的颜色并在被选中时提升。"有两个视频。右边显示了这个菜单应该是什么样子。我有一个像按钮这样的菜单工作得很完美,但我无法实现的是这个灰色的背景,它通过动作和任务栏阻止整个UI(如警报)...
正常:
并选择:
如您所见,材料设计指南告诉我们选定的FAB应该阻止整个UI。但我不知道如何......
所以我现在所拥有的: 我有一个global_fab.xml来保存我的两个FAB:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<RelativeLayout 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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:id="@+id/fab_background"
android:visibility="gone">
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/global_fab_mini"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="90dp"
android:layout_marginRight="24dp"
android:src="@drawable/ic_credentials_light"
android:theme="@style/Base.Widget.AppCompat.ImageButton"
android:visibility="gone"
app:backgroundTint="@color/cool_grey"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/global_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_add_light"
android:theme="@style/Base.Widget.AppCompat.ImageButton"
app:fabSize="normal"
android:visibility="visible" />
</RelativeLayout>
</layout>
此FAB具有相应的ViewGroup类:
package de.mycompany.ui.view;
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import com.mycompany.package.android.R;
import com.mycompany.package.android.databinding.GlobalFabBinding;
public class GlobalFABView extends FrameLayout implements IGlobalFABView {
private GlobalFabBinding globalFABViewBinding;
private Listener listener;
private boolean fabMenuOpen = false;
public GlobalFABView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GlobalFABView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
globalFABViewBinding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.global_fab, this, false);
addView(globalFABViewBinding.getRoot());
this.globalFABViewBinding.globalFab.setOnClickListener(this::globalFabClicked);
this.globalFABViewBinding.fabBackground.setOnClickListener(this::backgroundClicked);
}
private void globalFabClicked(View v) {
this.listener.mainFabClicked();
}
private void backgroundClicked(View v) {
this.listener.backgroundClicked();
}
@Override
public void show() {
}
@Override
public void hide() {
}
@Override
public void setListener(Listener listener) {
this.listener = listener;
}
@Override
public void toggleFabMenu() {
Animation fabAnimation = AnimationUtils.loadAnimation(this.getContext(), this.fabMenuOpen ?
R.anim.global_fab_close :
R.anim.global_fab_open);
final boolean fabMenuOpen = this.fabMenuOpen;
if (!fabMenuOpen) {
globalFABViewBinding.globalFabMini.setVisibility(VISIBLE);
}
globalFABViewBinding.fabBackground.setVisibility(
fabMenuOpen ? GONE : VISIBLE
);
fabAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// Nothing to do.
}
@Override
public void onAnimationEnd(Animation animation) {
if (fabMenuOpen) {
globalFABViewBinding.globalFabMini.setVisibility(GONE);
globalFABViewBinding.globalFab.setSelected(!fabMenuOpen);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
// Nothing to do.
}
});
globalFABViewBinding.globalFabMini.startAnimation(fabAnimation);
this.fabMenuOpen = !fabMenuOpen;
}
}
我的菜单打开和关闭没有问题(我有两个动画xmls)。后台RelativeLayout(+id/fab_background
)用于处理&#34;点击任意位置和关闭菜单&#34;事件。
现在我将其添加到我想要的任何活动中:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/fab_holder">
<include layout="@layout/app_bar_with_progress_bar" android:id="@+id/appbar"/>
<de.mycompany.ui.view.HomeView
android:id="@+id/home_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/appbar" />
<de.mycompany.ui.view.GlobalFABView
android:id="@+id/global_fab_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
答案 0 :(得分:0)
为了在整个屏幕上铺设一个新图层,我们需要启动一个透明的新活动。
我创建了一个包含菜单的活动。在我的正常活动中,我只添加了一个浮动操作按钮。在此单击操作中,我打开了没有动画的MenuActivity
,因此我可以设置浮动操作按钮菜单的外观动画。这是我的活动布局:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fab_background"
android:background="@color/fab_menu_background"
android:visibility="gone">
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/global_fab_mini"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="90dp"
android:layout_marginRight="24dp"
android:src="@drawable/ic_credentials_light"
android:theme="@style/Base.Widget.AppCompat.ImageButton"
android:visibility="gone"
app:backgroundTint="@color/cool_grey"
app:fabSize="mini" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/global_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_add_light"
android:theme="@style/Base.Widget.AppCompat.ImageButton"
app:fabSize="normal"
android:visibility="visible" />
<TextView
android:text="@string/fab_mini_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:id="@+id/fab_mini_label"
android:background="@drawable/fab_label_background"
android:gravity="center"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_marginRight="4dp"
android:elevation="2dp"
android:textSize="14dp"
android:layout_alignBottom="@+id/global_fab"
android:layout_toStartOf="@+id/global_fab"
android:visibility="gone"/>
<TextView
android:text="@string/fab_main_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fab_main_label"
android:background="@drawable/fab_label_background"
android:gravity="center"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:elevation="2dp"
android:textSize="14dp"
android:layout_marginBottom="41dp"
android:layout_above="@+id/fab_mini_label"
android:layout_alignStart="@+id/fab_mini_label"
android:visibility="gone" />
</RelativeLayout>
</layout>
在我的活动中,我有这个功能:
public void toggleFabMenu() {
Animation fabAnimation = AnimationUtils.loadAnimation(this.getContext(), this.fabMenuOpen ?
R.anim.global_fab_close :
R.anim.global_fab_open);
Animation labelAnimation = AnimationUtils.loadAnimation(this.getContext(), this.fabMenuOpen ?
R.anim.global_fab_labels_close :
R.anim.global_fab_labels_open);
Animation backgroundAnimation = AnimationUtils.loadAnimation(this.getContext(), this.fabMenuOpen ?
R.anim.global_fab_menu_background_close :
R.anim.global_fab_menu_background_open);
final boolean fabMenuOpen = this.fabMenuOpen;
if (!fabMenuOpen) {
globalFABViewBinding.globalFabMini.setVisibility(VISIBLE);
globalFABViewBinding.fabMiniLabel.setVisibility(VISIBLE);
globalFABViewBinding.fabMainLabel.setVisibility(VISIBLE);
globalFABViewBinding.fabBackground.setVisibility(VISIBLE);
}
fabAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
if (fabMenuOpen) {
globalFABViewBinding.globalFabMini.setVisibility(GONE);
globalFABViewBinding.fabMiniLabel.setVisibility(GONE);
globalFABViewBinding.fabMainLabel.setVisibility(GONE);
globalFABViewBinding.globalFab.setSelected(!fabMenuOpen);
}
}
@Override
public void onAnimationEnd(Animation animation) {
if (fabMenuOpen) {
globalFABViewBinding.fabBackground.setVisibility(GONE);
listener.menuDisappeared();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
// Nothing to do.
}
});
globalFABViewBinding.globalFabMini.startAnimation(fabAnimation);
globalFABViewBinding.fabMiniLabel.startAnimation(labelAnimation);
globalFABViewBinding.fabMainLabel.startAnimation(labelAnimation);
globalFABViewBinding.fabBackground.startAnimation(backgroundAnimation);
this.fabMenuOpen = !fabMenuOpen;
}
在动画中,我为标签和背景淡化动画,以及将我的fab迷你按钮移动到它所属的地方的过渡动画。
现在即使在状态栏上也适合背景的技巧是,我们做不到!所以我们必须找到一个解决方法,这不是很明显。首先,我想让活动全屏,但状态栏消失。所以我们必须让状态栏在那里,但我们需要让它透明。因此,我们看到状态栏的颜色位于它背后,可以覆盖我们的背景。为此,我创建了一个新主题:
<style name="Theme.Transparent" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:immersive">false</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="colorPrimaryDark">@android:color/transparent</item>
</style>
是。这正是我想要的。