简体   繁体   English

Android全屏阻止视图,例如Google Calendar FAB

[英]Android Full Screen blocking view like Google Calendar FAB

I'm trying to make a Floating Action Button Menu in my app. 我正在尝试在我的应用程序中制作一个浮动动作按钮菜单。 It should look like the FAB in the Google Calendar app, which is the kind of a active FAB shown by the Material Design Guideline: 它应该看起来像Google日历应用程序中的FAB,这是“材料设计指南”中显示的一种活动FAB:

See here: https://material.io/guidelines/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button 参见此处: https : //material.io/guidelines/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button

Under "The floating action button changes color on focus and lifts upon being selected." 在“浮动操作按钮会更改焦点上的颜色并在被选择时抬起”。 there are two videos. 有两个视频。 The right one shows what this menu should look like. 右侧显示该菜单的外观。 I have a menu like button that works perfectly but what I cannot achive is this gray background that blocks the whole UI (like an alert) with the action and task bar... 我有一个像按钮这样的菜单,可以很好地工作,但是我无法实现的是灰色的背景,它用操作和任务栏阻止了整个UI(例如警报)。

Normal: 正常:

正常

And selected: 并选择:

选

As you can see, the material design guideline tells us that a selected FAB should block the whole UI. 如您所见,材料设计指南告诉我们,选定的FAB应该会阻塞整个UI。 But I don't know how... 可是我不知道

So what I have at the moment: I have a global_fab.xml that holds my two FABs: 因此,我现在拥有的是:我有一个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>

This FAB has a corresponding ViewGroup Class: 此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;
    }
}

My menu opens and closes without problems (I have two anim xmls for this). 我的菜单打开和关闭都没有问题(为此,我有两个anim xml)。 The Background RelativeLayout ( +id/fab_background ) is there to handle the "click anywhere and close menu" event. 后台RelativeLayout( +id/fab_background )用于处理“单击任意位置并关闭菜单”事件。

Now I add this into any activty I want it: 现在,将其添加到我想要的任何活动中:

<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>

OK, I got this. 好我知道了

in order to lay a new layer over the whole screen we need to start a new activity that is transparent. 为了在整个屏幕上放置一个新层,我们需要启动一个透明的新活动。 I created an activity that holds the menu. 我创建了一个包含菜单的活动。 Into my normal activity I only added one Floating Action Button. 在我的正常活动中,我仅添加了一个“浮动动作”按钮。 In the click action of this, I open my MenuActivity without animations, so I can animate the appearance of the Floating Action Button Menu. 在此单击动作中,我没有动画打开了MenuActivity ,因此可以为“浮动动作按钮菜单”的外观设置动画。 This is my Activity Layout: 这是我的活动布局:

<?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>

In my Activity I have this function: 在我的活动中,我具有以下功能:

    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;
    }

In the animations I have fade animations for the labels and the background and a transition animation that moves my fab mini button to the place it belongs. 在动画中,我具有用于标签和背景的淡入淡出动画,以及用于将fab mini按钮移至其所属位置的过渡动画。

Now the trick to fit the background even over the status bar is, we cannot do it! 现在,即使在状态栏上也适合背景的诀窍是,我们做不到! So we have to find a workaround and this is not very obvious. 因此,我们必须找到一种解决方法,但这并不是很明显。 First I thought to make the activity fullscreen but then the status bar disappears. 首先,我考虑将活动设置为全屏显示,但是状态栏消失了。 So we have to let the status bar there but we need to make it transparent. 因此,我们必须将状态栏放在那里,但我们需要使其透明。 So we see the color of the statusbar that lays behind it and can lay over our background. 因此,我们看到了位于其后面的状态栏的颜色,并且可以覆盖我们的背景。 To do this I created a new theme: 为此,我创建了一个新主题:

<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>

Yes. 是。 this is exactly what I want. 这正是我想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM