棒棒糖上完全透明的状态栏和导航栏

ren*_*zhn 43 android android-5.0-lollipop

我正在尝试制作一个Android启动器.我想实现一个完全透明的状态栏和导航栏,这里是我的主题xml文件.

<resources>
    <style name="Theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">false</item>
    </style>
</resources>
Run Code Online (Sandbox Code Playgroud)

最后两个项目不起作用,棒棒糖还有一个阴影.

这就是它的样子(注意状态栏和导航栏上实际上有一个阴影): 在此输入图像描述

我想要达到的目标(新星发射器):

在此输入图像描述

如何使状态栏和导航栏"透明"而不是"半透明"?

Mac*_*ado 121

更新

您可以在KitKat上以编程方式实现相同的效果,然后通过在其中设置FLAG_LAYOUT_NO_LIMITS标志来实现Window.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window w = getWindow(); // in Activity's onCreate() for instance
            w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        }
Run Code Online (Sandbox Code Playgroud)

如果您为布局设置背景资源(如颜色或图片),您将在状态栏的"下方"看到颜色或图片.

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/primary_dark</item>
Run Code Online (Sandbox Code Playgroud)

原始答案

它看起来像android:windowTranslucentStatusandroid:windowTranslucentNavigation应该true代替false

<resources>
    <style name="Theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:navigationBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>
Run Code Online (Sandbox Code Playgroud)

此外,透明活动/容器布局需要此属性集:

android:fitsSystemWindows="true"
Run Code Online (Sandbox Code Playgroud)

资源

  • 这个答案不适合使用底部导航栏的应用程序,因为它会丢失限制并将导航底栏向下放到手机软键. (16认同)
  • 当我应用它时,导航和状态栏仍然具有灰色半透明颜色,如[here](http://i.imgur.com/3s1kZhd.png)所示.在Lollipop和M.上测试任何想法为什么? (6认同)
  • 这怎么是正确答案呢?NO_LIMITS 使内容同时绘制在状态栏和导航栏上。目标只是使导航栏完全透明。 (2认同)

Arp*_*kar 8

您可以使用此科特林扩展功能将设置状态栏完全透明(在API 23+View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR可用的标志API 23+)和导航栏(API 27+View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR可用的标志API 27+),否则它将使用systemUiScrimAPI 21+

fun Activity.transparentStatusAndNavigation(
    systemUiScrim: Int = Color.parseColor("#40000000") // 25% black
) {
    var systemUiVisibility = 0
    // Use a dark scrim by default since light status is API 23+
    var statusBarColor = systemUiScrim
    //  Use a dark scrim by default since light nav bar is API 27+
    var navigationBarColor = systemUiScrim
    val winParams = window.attributes


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        statusBarColor = Color.TRANSPARENT
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        systemUiVisibility = systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
        navigationBarColor = Color.TRANSPARENT
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        systemUiVisibility = systemUiVisibility or
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        window.decorView.systemUiVisibility = systemUiVisibility
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        winParams.flags = winParams.flags or
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        winParams.flags = winParams.flags and
                (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
                        WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION).inv()
        window.statusBarColor = statusBarColor
        window.navigationBarColor = navigationBarColor
    }

    window.attributes = winParams
}
Run Code Online (Sandbox Code Playgroud)

API 21+ API 21+ API 27+ API 27+


小智 7

对于 API 29 及以上使用

<style name="Your.Theme">
    <item name="android:navigationBarColor">@android:color/transparent</item>
    <item name="android:enforceNavigationBarContrast">false</item>
</style>
Run Code Online (Sandbox Code Playgroud)

  • 您能详细说明一下原因吗? (2认同)

Aha*_*kat 6

100% 工作代码

完全透明的状态栏和导航栏

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initStatusNavBar();
    transparentStatusAndNavigation();

    showSystemUI();
    // hideSystemUI();

}

public static void transparentStatusAndNavigation(Activity activity) {

    Window window = activity.getWindow();

    // make full transparent statusBar
    if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
        setWindowFlag(window, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
    }
    if (Build.VERSION.SDK_INT >= 19) {
        int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        visibility = visibility | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        window.getDecorView().setSystemUiVisibility(visibility);
    }
    if (Build.VERSION.SDK_INT >= 21) {
        int windowManager = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        windowManager = windowManager | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
        setWindowFlag(window, windowManager, false);
        window.setStatusBarColor(Color.TRANSPARENT);
        window.setNavigationBarColor(Color.TRANSPARENT);
    }

}

private static void setWindowFlag(final int bits, boolean on) {
    Window win = getWindow();
    WindowManager.LayoutParams winParams = win.getAttributes();
    if (on) {
        winParams.flags |= bits;
    } else {
        winParams.flags &= ~bits;
    }
    win.setAttributes(winParams);
}
Run Code Online (Sandbox Code Playgroud)

设置状态栏和导航栏高度和颜色:

在activity_main.xml 中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical">

    <View
        android:id="@+id/status_bg"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/primaryColorLightThemeDarkTrans"
        tools:layout_height="24dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <!--Write Code Here-->

    </LinearLayout>

    <View
        android:id="@+id/nav_bg"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/navColorLightThemeTrans"
        tools:layout_height="?actionBarSize" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

在java代码中:

private void initStatusNavBar() {
    int statusBarHeight = getStatusBarHeight(activity);
    int navBarHeight = getNavigationBarHeight(activity, statusBarHeight);

    View statusBarBackground = findViewById(R.id.status_bg);
    statusBarBackground.getLayoutParams().height = statusBarHeight;

    View navBarBackground = findViewById(R.id.nav_bg);
    if (Build.VERSION.SDK_INT >= 21) {
        setNavigationBarHeight(activity, navBarBackground);
    } else {
        navBarBackground.getLayoutParams().height = navBarHeight;
    }
}

public static int getStatusBarHeight(Activity activity) {
    final Resources resources = activity.getResources();
    final int resId = resources.getIdentifier("status_bar_height", "dimen", "android");
    if (resId > 0) {
        return resources.getDimensionPixelSize(resId);
    }
    return 0;
}

public static int getNavigationBarHeight(Activity activity, int statusBarHeight) {
    Point point = getNavigationBarSize(activity);
    int height = point.y;
    if (isNotchDisplay(statusBarHeight)) {
        height = height - statusBarHeight;
    }
    return height;
}

private static Point getNavigationBarSize(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Point appUsableSize = getAppUsableScreenSize(context);
        Point realScreenSize = getRealScreenSize(context);

        // navigation bar on the right
        if (appUsableSize.x < realScreenSize.x) {
            return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
        }

        // navigation bar at the bottom
        if (appUsableSize.y < realScreenSize.y) {
            return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
        }

        // navigation bar is not present
        return new Point();
    }
    return new Point();
}

private static Point getAppUsableScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Point size = new Point();
    if (null != windowManager) {
        Display display = windowManager.getDefaultDisplay();
        display.getSize(size);
    }
    return size;
}

private static Point getRealScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Point size = new Point();
    if (null != windowManager) {
        Display display = windowManager.getDefaultDisplay();

        if (Build.VERSION.SDK_INT >= 17) {
            display.getRealSize(size);
        } else {
            try {
                size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
                size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    return size;
}

private static boolean isNotchDisplay(int statusBarHeight) {
    int normalStatusBarHeight = dpToPxForNav(25);
    return statusBarHeight > normalStatusBarHeight;
}

private static int dpToPxForNav(float dp) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}

public static void setNavigationBarHeight(Activity activity, View navBarBackground) {
    ViewCompat.setOnApplyWindowInsetsListener(navBarBackground, (v, insets) -> {
        int navBarHeight = insets.getSystemWindowInsetBottom();
        navBarBackground.getLayoutParams().height = navBarHeight;
        return insets.consumeSystemWindowInsets();
    });
}


@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void showSystemUI() {
    statusBarBackground.setVisibility(View.VISIBLE);
    navBarBackground.setVisibility(View.VISIBLE);
    mDecorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void hideSystemUI() {
    statusBarBackground.setVisibility(View.GONE);
    navBarBackground.setVisibility(View.GONE);
    mDecorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Run Code Online (Sandbox Code Playgroud)

style.xml 中的主题:

<style name="MyAppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">

    <!--For Notch Issues-->
    <item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>

    <item name="windowActionBarOverlay">true</item>

    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorControlHighlight">@color/colorHighlight</item>
    <item name="android:windowBackground">@android:color/white</item>
    <item name="android:textColorPrimary">#fff6d7</item>

    <item name="android:colorPrimary" tools:targetApi="lollipop">@color/primaryColor</item>
    <item name="android:colorPrimaryDark" tools:targetApi="lollipop">@color/primaryColorDark</item>
    <item name="android:statusBarColor" tools:targetApi="lollipop">@color/primaryColorDark</item>
    <item name="android:colorAccent" tools:targetApi="lollipop">@color/accentColorLight</item>
    <item name="android:colorControlHighlight" tools:targetApi="lollipop">@color/colorHighlight</item>

    <item name="android:navigationBarColor" tools:targetApi="lollipop">@color/navColor</item>

    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>

</style>
Run Code Online (Sandbox Code Playgroud)

在 AndroidManifest.xml 中:

    <activity
        android:name="com.MyActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="fullSensor"
        android:theme="@style/MyAppTheme" />
Run Code Online (Sandbox Code Playgroud)

  • 不适用于搭载 Android 9 的 Pixel 2 XL。还将底部软件按钮栏更改为没有可见按钮的白色栏。 (3认同)

den*_*try 5

我使用它是因为它保持状态栏和导航栏的高度

<!-- Base application theme. -->
<style name="theme" parent="android:Theme.Material.Wallpaper.NoTitleBar">
    <item name="android:navigationBarColor">#00000000</item>
    <item name="android:statusBarColor">#00000000</item>
</style>
Run Code Online (Sandbox Code Playgroud)

这确实需要API 21+

  • 对我不起作用。您还使用哪些其他属性? (2认同)

Way*_*yne 4

您需要android:windowDrawsSystemBarBackgrounds为您的主题添加标志

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
Run Code Online (Sandbox Code Playgroud)

或者在 onCreate() 中调用它

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
Run Code Online (Sandbox Code Playgroud)

  • @nhaarman 你也需要添加这个。窗口 w = getWindow(); w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); (3认同)
  • 这不会使导航栏透明。 (2认同)