Lollipop: 在 statusBar 后面绘制,并将其颜色设置为透明

我已经将我的状态栏的颜色设置为透明的棒棒糖只与下面的行在我的主题:

<item name="android:statusBarColor">@android:color/transparent</item>

现在我需要在它后面画画,但是我不能在它后面画任何视图。我知道如何使用 windowTranslucentStatus属性,但是不想使用这个属性,因为它会忽略 statusBar 设置为透明的颜色。

172111 次浏览

您可以使用 ScrimInsetFrameLayout

Https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/scriminsetsframelayout.java

Android: fitsSystemWindows = “ true”应该设置为 Scrim 布局!

而不是

<item name="android:statusBarColor">@android:color/transparent</item>

使用以下方法:

<item name="android:windowTranslucentStatus">true</item>

并确保删除“ MainActivity”布局上的顶部填充(默认添加)。

请注意,这不会使状态栏完全透明,并且仍然会有一个“褪色的黑色”覆盖在您的状态栏上。

方法一:

要实现完全透明的状态栏,您必须使用 statusBarColor,它只能在 API 21及以上版本中使用。windowTranslucentStatus在 API 19及以上版本中可用,但它为状态栏添加了有色背景。然而,设置 windowTranslucentStatus确实实现了一件事情,改变 statusBarColor为透明不: 它设置的 SYSTEM_UI_FLAG_LAYOUT_STABLE 以及 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN旗帜。获得相同效果的最简单方法是手动设置这些标志,这样可以有效地禁用 Android 布局系统强加的插入,让您自己照顾自己。

onCreate方法中调用这一行:

getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

还要确保在/res/values-v21/styles.xml 中设置透明度:

<item name="android:statusBarColor">@android:color/transparent</item>

或者以编程方式设置透明度:

getWindow().setStatusBarColor(Color.TRANSPARENT);

这种方法的好的一面是,相同的布局和设计也可以用在 API 19上,通过交换有色半透明状态栏的透明状态栏。

<item name="android:windowTranslucentStatus">true</item>

方法二:

如果你只需要在状态栏下面画一个背景图片,而不是在背景后面定位一个视图,这可以通过简单地将活动主题的背景设置为想要的图片,并设置状态栏透明度来实现,如方法1所示。这就是几个月前我用来创建 Android Police 文章截图的方法。

方法三:

如果您必须忽略某些布局的标准系统插入,而让它们在其他布局中继续工作,那么唯一可行的方法是使用经常链接的 ScrimInsetsFrameLayout类。当然,在这个类中所做的一些事情并不是所有场景都必需的。例如,如果您不打算使用合成状态栏覆盖,那么只需注释掉 init()方法中的所有内容,并且不需要向 attrs.xml 文件添加任何内容。我已经看到了这种方法的工作,但是我认为您会发现它带来了一些其他的含义,这可能需要大量的工作才能解决。

我还看到您反对包装多个布局。在将一个布局包装在另一个布局中的情况下(其中两个布局都有 match_parent作为高度和宽度) ,性能影响太小,无需担心。无论如何,您可以通过将它从 FrameLayout扩展的类更改为您喜欢的任何其他类型的 Layout 类来完全避免这种情况。一切都会好起来的。

这对我的案子有帮助


// Create/Set toolbar as actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);


// Check if the version of Android is Lollipop or higher
if (Build.VERSION.SDK_INT >= 21) {


// Set the status bar to dark-semi-transparentish
getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);


// Set paddingTop of toolbar to height of status bar.
// Fixes statusbar covers toolbar issue
toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
}

// A method to find height of the status bar
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}

有关使用 statusBar 的详细信息,请参阅 Youtube.com/watch?v=_mgdmvro3ie


试试这个主题

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="colorPrimaryDark">@android:color/transparent</item>
<item name="colorPrimary">@color/md_blue_200</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
</style>

确保,你的布局设置

android:fitsSystemWindows="false"

在 Android Studio 1.4中,模板项目使用锅炉板代码在 AppbarLayout 和/或 Toolbar 上设置 Overlay主题。它们还被设置为在状态栏后面通过 fitSystemWindow属性 = true 呈现。这将导致只有工具栏呈现在状态栏的正下方,其他所有内容都将呈现在工具栏的正下方。因此,上面提供的解决方案不会自己起作用。您必须进行以下更改。

  • 删除 叠加主题或更改为工具栏的非覆盖主题。
  • Style-21.xml文件中放入以下代码。

    @ android: 颜色/透明

  • 中包含导航抽屉的活动分配此主题 AndroidManifest.xml文件

这将使“导航”抽屉显示在透明状态栏的后面。

类似的一些解决方案张贴,但在我的情况下,我做了状态栏透明和固定的位置与一些负边距操作栏

if (Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) toolbar.getLayoutParams();
lp.setMargins(0, -getStatusBarHeight(), 0, 0);
}

我在工具栏和根视图中使用

android:fitsSystemWindows="true"

我也有同样的问题,所以我创建了 ImageView,它在状态栏 API 19 + 后面绘制

在状态栏 Gist.github.com后面设置自定义图像

public static void setTransparent(Activity activity, int imageRes) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
// set flags
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}


// get root content of system window
//ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
// rootView.setFitsSystemWindows(true);
// rootView.setClipToPadding(true);


ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
if (contentView.getChildCount() > 1) {
contentView.removeViewAt(1);
}


// get status bar height
int res = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int height = 0;
if (res != 0)
height = activity.getResources().getDimensionPixelSize(res);


// create new imageview and set resource id
ImageView image = new ImageView(activity);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
image.setLayoutParams(params);
image.setImageResource(imageRes);
image.setScaleType(ScaleType.MATRIX);


// add image view to content view
contentView.addView(image);
// rootView.setFitsSystemWindows(true);


}

来自 Cody Toombs 差不多的解决方案帮了我大忙。我不知道这是否与 Xamarin有关,但我现在有一个可以接受的解决方案:

Example

这是我的装置:

我有一个 Android 项目,我已经引用了 Android。支持 v4和 v7包。我定义了两种风格:

Value/styles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>

Value-v21/styles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<style name="MyStyle" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>

AndroidManifest 的目标是“ MyStyle”:

Xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.agn.test.test">
<uses-sdk android:minSdkVersion="10" />
<application android:allowBackup="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:theme="@style/MyStyle">
</application>
</manifest>

最后是主要活动中的代码:

[Activity (Label = "Test", MainLauncher = true, Icon = "@mipmap/icon")]
public class MainActivity : Activity
{
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);


SetContentView (Resource.Layout.Main);
//Resource.Layout.Main is just a regular layout, no additional flags. Make sure there is something in there like an imageView, so that you can see the overlay.


var uiOptions = (int)Window.DecorView.SystemUiVisibility;
uiOptions ^= (int)SystemUiFlags.LayoutStable;
uiOptions ^= (int)SystemUiFlags.LayoutFullscreen;
Window.DecorView.SystemUiVisibility = (StatusBarVisibility)uiOptions;


Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds);
}
}

请注意,我设置了 DrawsSystemBarBackground 标志,这使得一切都不同了

Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds);

我花了很多时间,事实上,花了太多时间。希望这个答案能够帮助任何想要达到同样目标的人。

正确的解决方案是将 Activity 标签下的 XML 属性更改为以下样式

  android:theme="@style/Theme.AppCompat.Light.NoActionBar"

下面是我用来完成这个任务的主题:

<style name="AppTheme" parent="@android:style/Theme.NoTitleBar">


<!-- Default Background Screen -->
<item name="android:background">@color/default_blue</item>
<item name="android:windowTranslucentStatus">true</item>


</style>

有很好的库 StatusBarUtil@ laobie,有助于轻松地绘制图像在 StatusBar。

只要加上你的 build.gradle:

compile 'com.jaeger.statusbarutil:library:1.4.0'

然后在 Activity 集中

StatusBarUtil.setTranslucentForImageView(Activity activity, int statusBarAlpha, View viewNeedOffset)

在布局上

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


<ImageView
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:adjustViewBounds="true"
android:layout_height="wrap_content"
android:src="@drawable/toolbar_bg"/>


<android.support.design.widget.CoordinatorLayout
android:id="@+id/view_need_offset"
android:layout_width="match_parent"
android:layout_height="match_parent">


<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>


<!-- Your layout code -->
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

更多信息下载 小样或克隆从 Github 页面和发挥所有功能。

注: 支持 KitKat 及以上版本。

希望能帮到别人!

@ Cody Toombs 的回答引出了一个问题: 导航栏后面的布局。因此,我发现使用 这个解决方案由@Kriti 提供

下面是同样的 Kotlin 代码片段:

if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true)
}


if (Build.VERSION.SDK_INT >= 19) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}


if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false)
getWindow().setStatusBarColor(Color.TRANSPARENT)
}


private fun setWindowFlag(activity: Activity, bits: Int, on: Boolean) {


val win: Window = activity.getWindow()


val winParams: WindowManager.LayoutParams = win.getAttributes()
if (on) {
winParams.flags = winParams.flags or bits
} else {
winParams.flags = winParams.flags and bits.inv()
}
win.setAttributes(winParams)
}

您还需要添加

android:fitsSystemWindows="false"

布局的根视图。

您所需要做的就是在主题中设置这些属性

<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>

这个被接受的答案对我来说使用 CollapsingToolbarLayout 很有效。值得注意的是,setSytstemUiVisibility()覆盖了以前对该函数的所有调用。因此,如果在其他地方对同一视图使用该函数,则需要包含 View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN标志,否则它们将被新调用覆盖。

这就是我的情况,一旦我把这两个标志添加到另一个地方,我正在打电话给 setSystemUiVisibility(),接受的答案工作得非常完美。

我将在这里添加一些更多的信息。最新的 Android 开发使得在状态栏中处理很多情况变得非常容易。以下是我对 styles.xml的观察

  1. 背景颜色 : 对于 SDK 21 + ,正如很多答案所提到的,<item name="android:windowTranslucentStatus">true</item>将使状态栏透明并显示在 UI 前面。你的活动将占据整个顶部的空间。
  2. 背景颜色 : 同样,对于 SDK 21 + ,<item name="android:statusBarColor">@color/your_color</item>将简单地为您的状态栏提供一种颜色,而不会影响其他任何东西。

  3. 然而,在后来的设备(Android M/+)中,图标开始以不同的色调出现。如果你在 values-23文件夹中覆盖你的 styles.xml文件并添加 <item name="android:windowLightStatusBar">true</item>,操作系统可以给 SDK 23/+ 的图标一个深灰色阴影。
    这样,如果你的状态栏是浅色的,你就可以为你的用户提供一个更加可见的状态栏(想想很多谷歌应用程序都是浅色背景,但是图标却是灰色的)。
    我建议你使用这个,如果你给你的状态栏通过点 # 2

  4. 颜色
  5. 在最新的设备中,SDK 29/+ 提供了一个系统范围的明暗主题,可由用户控制。作为开发人员,我们也应该覆盖我们的样式文件在一个新的 values-night文件夹,给用户2个不同的体验。
    在这里,我再次发现第2点在提供“背景颜色到状态栏”方面是有效的。但是系统并没有改变我的应用程序状态栏图标的颜色。由于我今天的风格版本包含了较轻的主题,这意味着用户将遭受低可见性(白色图标在较轻的背景)
    这个问题可以通过使用点 # 3方法或者重写 values-29文件夹中的样式文件并使用较新的 api <item name="android:enforceStatusBarContrast">true</item>来解决。如果背景颜色太浅,这将自动加强图标的灰色调。