【问题标题】:Android Full Screen blocking view like Google Calendar FABAndroid 全屏阻止视图,如 Google 日历 FAB
【发布时间】:2017-07-17 20:54:53
【问题描述】:

我正在尝试在我的应用中创建一个浮动操作按钮菜单。它应该看起来像 Google 日历应用中的 FAB,这是 Material Design Guideline 中显示的活动 FAB:

请看这里: https://material.io/guidelines/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button

在“浮动操作按钮在焦点上改变颜色并在被选中时提升”下。有两个视频。右边显示了这个菜单应该是什么样子。我有一个类似按钮的菜单,可以完美运行,但我无法实现的是灰色背景,它通过操作和任务栏阻止了整个 UI(如警报)......

正常:

并选择:

如您所见,材料设计指南告诉我们,选定的 FAB 应该阻止整个 UI。但我不知道怎么...

所以我现在拥有的: 我有一个包含我的两个 FAB 的 global_fab.xml:

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

我的菜单打开和关闭都没有问题(为此我有两个动画 xml)。 Background RelativeLayout (+id/fab_background) 用于处理“单击任意位置并关闭菜单”事件。

现在我将它添加到我想要的任何活动中:

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

【问题讨论】:

  • 你能发布你的xml布局吗?
  • @SanjayKakadiya 添加了我的 xml 内容。

标签: android floating-action-button


【解决方案1】:

好的,我知道了。

为了在整个屏幕上放置一个新层,我们需要启动一个透明的新活动。 我创建了一个包含菜单的活动。在我的正常活动中,我只添加了一个浮动操作按钮。在这个点击动作中,我打开我的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>

是的。这正是我想要的。

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 2021-05-19
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    相关资源
    最近更新 更多