【问题标题】:Why does my layout get messed up after clearing FLAG_TRANSLUCENT_STATUS flag?为什么我的布局在清除 FLAG_TRANSLUCENT_STATUS 标志后会变得混乱?
【发布时间】:2015-12-07 06:25:49
【问题描述】:

我有一个 Activity 应用程序。它显示一个LoginFragment,它使状态栏和导航栏半透明,以便它可以在其后面显示背景图像。但是,登录后,该片段被另一个片段替换,该片段需要显示通常的实心状态和导航栏。因此,在删除 LoginFragment 之前,它会取消设置它设置的标志,以使条形不透明。

我面临的问题是,在我登录后,具有正常状态和导航栏的片段的操作栏向下移位。如果我将屏幕旋转为横向,然后再旋转回纵向以强制重新布局布局,则操作栏会弹回正确的位置。

当状态栏是半透明的。这很好。

在下一个屏幕上,操作栏向下移动。另请注意,状态栏是黑色的,根据主题应该是灰色的。

现在如果我回到第一个屏幕,顶部的半透明条没问题,但整个内容向上移动,下面留下一个空白区域。

LoginFragment 中的代码以编程方式使条形变为半透明并恢复它们:-

@Override
public void onResume() {
    super.onResume();
    if (hasTransparentStatusBar()) {
        setStatusBarTranslucent();
    }
}

@Override
public void onPause() {
    if (hasTransparentStatusBar()) {
        setStatusBarOpaque();
    }
    super.onPause();
}

protected boolean hasTransparentStatusBar() {
    return true;
}

protected void setStatusBarTranslucent() {
    if (Build.VERSION.SDK_INT >= 21) {
        Window window = getActivity().getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
}

protected void setStatusBarOpaque() {
    if (Build.VERSION.SDK_INT >= 21) {
        Window window = getActivity().getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
}

Activity的布局xml:-

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.app.MainActivity" >

    <!-- The main content view -->

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- The navigation drawer -->

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@color/divider"
        android:dividerHeight="0dp"
        android:background="@color/primary"
        />

</android.support.v4.widget.DrawerLayout>

LoginFragment的布局xml:-

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="200dp"
    android:src="@drawable/logo"
    android:id="@+id/logo"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />

<Button
    android:padding="@dimen/default_margin"
    android:text="Login using Facebook"
    android:textColor="@android:color/white"
    android:background="@drawable/com_facebook_button_background"
    android:id="@+id/authButton"
    android:layout_below="@+id/logo"
    android:layout_centerHorizontal="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

【问题讨论】:

  • 最后解决这个问题的唯一解决方法是我将LoginFragment 移动到另一个以沉浸式模式显示其片段的新活动下。其余的 Fragment 仍然由原始 Activity 提供服务。
  • 我也遇到了类似的问题,但使用的是视图而不是片段。对我来说,w.getDecorView().requestApplyInsets() 在清除半透明标志后工作。
  • 这应该是 Froyo 接受的答案,我要发布它!

标签: android android-layout android-fragments


【解决方案1】:

我之前也遇到过同样的问题,所以如果有人偶然发现这个问题,正确的解决方法是设置 NO_LIMITS 标志:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}

【讨论】:

  • 我完全不知道为什么,但我确认这是可行的(设置 FLAG_LAYOUT_NO_LIMITS 而不是 FLAG_TRANSLUCENT_STATUS 会使状态栏半透明,并且不会在底部留下空白)。
  • 这会导致具有 UI 导航栏而不是硬件按钮的设备(例如 Nexus 5X)上的导航栏出现问题
  • 同意yuval,这个flag让设备的软导航变得透明,慎用
【解决方案2】:

在透明状态栏的窗口上设置所有这些标志之后。 致电w.getDecorView().requestApplyInsets() 可解决此问题。 归功于 cmets 中的@Froyo

【讨论】:

    【解决方案3】:

    我有类似的问题,看来我们应该在onActivityCreated(Bundle) 之前设置窗口标志。 我经常使用静态方法来显示我的片段,如下所示:

    public class FragmentPlayer extends MediaFragment
    {
    
        public FragmentPlayer()
        {
            // Default public constructor required. 
        }
    
        public static void show(@NonNull Activity activity, boolean compact)
        {
            boolean isOrientationPortrait = UiHelper.isOrientationPortrait(activity);
            setupWindow(activity.getWindow(), isOrientationPortrait, compact);
    
            FragmentManager fragmentManager = activity.getFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            FragmentPlayer newFragment = FragmentPlayer.getInstance(compact);
            transaction.replace(R.id.fragment_player, newFragment);
            transaction.commit();
        }
    
        private static void setupWindow(@NonNull Window window, final boolean isOrientationPortrait,
                                        final boolean compact)
        {
            if (compact)
            {
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            }
            else
            {
                if (isOrientationPortrait)
                {
                    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                }
                else
                {
                    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                }
            }
        }   
    }
    

    如您所见,我将所有 Window 初始化从 onCreateActivity(Bundle) 移至静态方法 setupWindow(Window, boolean, boolean),现在一切正常。

    仍然不知道为什么从 onCreateActivity(Bundle) 调用这些方法时布局实际上会变得一团糟,但这就是开始。

    编辑 1: 哦,别忘了在 Activity.onCreate(Bundle) 中设置您的 Window 以正确处理屏幕旋转!

    【讨论】:

      【解决方案4】:

      我尝试了所有可能的方法来解决这个问题,并找到了一个明确的解决方案。 首先做youtube video中显示的事情 并将android:fitsSystemWindows="true" 添加到xml 中的android.support.v7.widget.Toolbar

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-01
        • 2015-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多