web-dev-qa-db-fra.com

Lollipop: dessinez derrière statusBar avec sa couleur définie sur transparente

J'ai défini la couleur de ma barre de statut sur Transparent pour Lollipop uniquement avec la ligne suivante dans mon thème:

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

Maintenant, je dois dessiner derrière, mais je ne peux pas en tirer de vue. Je sais comment le faire avec la propriété windowTranslucentStatus, mais je ne souhaite pas utiliser cette propriété car elle ignorera alors la couleur du statusBar défini sur transparent.

114
alxscms

Méthode n ° 1:

Pour obtenir une barre d'état complètement transparente, vous devez utiliser statusBarColor, qui n'est disponible que sur l'API 21 et les versions ultérieures. windowTranslucentStatus est disponible sur les API 19 et supérieures, mais ajoute un fond teinté pour la barre d'état. Cependant, définir windowTranslucentStatus permet d'obtenir une chose qui ne change pas statusBarColor en transparent: cela définit les indicateurs SYSTEM_UI_FLAG_LAYOUT_STABLE Et SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN. Le moyen le plus simple d'obtenir le même effet consiste à définir manuellement ces indicateurs, ce qui désactive efficacement les incrustations imposées par le système de présentation Android et vous permet de vous débrouiller seul.

Vous appelez cette ligne dans votre méthode onCreate:

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

Assurez-vous également de définir la transparence dans /res/values-v21/styles.xml:

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

Ou définissez la transparence par programme:

getWindow().setStatusBarColor(Color.TRANSPARENT);

Le bon côté de cette approche est que les mêmes présentations et conceptions peuvent également être utilisées sur l’API 19 en échangeant la barre d’état transparente contre la barre d’état translucide teintée.

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

Méthode n ° 2:

Si vous devez uniquement peindre une image d'arrière-plan sous votre barre d'état, au lieu de placer une vue derrière celle-ci, vous pouvez simplement définir l'arrière-plan du thème de votre activité sur l'image souhaitée et définir la transparence de la barre d'état comme indiqué dans la méthode # 1. C’est la méthode que j’ai utilisée pour créer les captures d’écran pour le article Android Police d’il ya quelques mois.

Méthode n ° 3:

Si vous devez ignorer les encarts système standard de certaines présentations tout en les conservant dans d’autres, le seul moyen viable consiste à travailler avec la classe ScrimInsetsFrameLayout souvent liée. Bien sûr, certaines des tâches effectuées dans cette classe ne sont pas nécessaires dans tous les scénarios. Par exemple, si vous ne prévoyez pas d’utiliser la superposition de la barre d’état synthétique, commentez simplement tous les éléments de la méthode init() sans rien ajouter au fichier attrs.xml. J'ai vu cette approche fonctionner, mais je pense que vous constaterez que cela entraîne d'autres implications qui peuvent nécessiter beaucoup de travail.

J'ai également vu que vous vous opposiez à l'utilisation de plusieurs mises en page. Dans le cas de l'intégration d'une mise en page dans une autre, où les deux ont match_parent en hauteur et en largeur, les conséquences sur les performances sont trop simples pour que vous puissiez vous en soucier. Quoi qu'il en soit, vous pouvez entièrement éviter cette situation en modifiant la classe qui va de FrameLayout à tout autre type de classe Layout de votre choix. Cela fonctionnera très bien.

341
Cody Toombs

Cela a fonctionné pour mon cas


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

Pour plus d'informations sur l'utilisation de statusBars: youtube.com/watch?v=_mGDMVRO3iE


39
Michael

Essayez ce thème

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

Assurez-vous que votre ensemble de mise en page 

Android:fitsSystemWindows="false"
21
Son Nguyen Thanh

Au lieu de 

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

Utilisez le suivant:

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

Et assurez-vous de supprimer le remplissage supérieur (qui est ajouté par défaut) sur votre présentation "MainActivity".

Notez que cela ne rend pas la barre d'état complètement transparente et qu'il y aura toujours une superposition "noir fané" sur votre barre d'état. 

10
Jeroen Mols

La solution de Cody Toombs presque a fait l'affaire pour moi. Je ne sais pas s'il s'agit de Xamarin ou pas, mais j'ai une solution acceptable:

 Example

Ceci est ma configuration:

J'ai un projet Android où j'ai référencé les packages Android.Support v4 et v7. J'ai deux styles définis:

values ​​/ 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>

values-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 vise "MyStyle":

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

Et enfin le code dans l'activité principale:

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

Notez que je mets le drapeau DrawsSystemBarBackgrounds, cela fait toute la différence

Window.AddFlags (WindowManagerFlags.DrawsSystemBarBackgrounds); 

J'ai passé beaucoup de temps à bien faire les choses, trop de temps en fait. Espérons que cette réponse aide tous ceux qui essaient de faire la même chose.

7
Gerhard Schreurs

La réponse de @Cody Toombs a entraîné un problème qui amène la mise en page derrière la barre de navigation. Donc, ce que j'ai trouvé utilise this solution donnée par @Kriti 

voici l'extrait de code Kotlin pour le même:

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

Vous devez également ajouter

Android:fitsSystemWindows="false"

vue racine de votre mise en page.

1
KishanSolanki124

Vous pouvez utiliser ScrimInsetFrameLayout 

https://github.com/google/iosched/blob/master/Android/src/main/Java/com/google/samples/apps/iosched/ui/widget/ScrimInsetsFrameLayout.Java

Android: fitsSystemWindows = "true" doit être défini sur la disposition du canevas!

Semblable à certaines des solutions publiées, mais dans mon cas, j'ai transparent la barre d'état et fixé la position de la barre d'action avec une marge négative

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

Et j'ai utilisé dans la barre d'outils et la vue racine

Android:fitsSystemWindows="true"
1
jegumi

J'ai eu le même problème alors je crée ImageView qui dessine derrière la barre d'état API 19+

Définir une image personnalisée derrière la barre d'état 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);

}
1
Sumit

Tout ce que vous avez à faire est de définir ces propriétés dans votre thème.

<item name="Android:windowTranslucentStatus">true</item>
<item name="Android:windowTranslucentNavigation">true</item>
0
Sudhir singh

Il y a une bonne bibliothèque StatusBarUtil from @laobie qui permet de dessiner facilement des images dans la barre de contrôle.

Ajoutez simplement dans votre build.gradle:

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

Puis dans le set d'activités 

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

Dans la mise en page

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

Pour plus d'informations, téléchargez demo ou clonez depuis github page et jouez avec toutes les fonctionnalités.

Remarque: Support KitKat et ci-dessus.

J'espère que ça aide quelqu'un d'autre!

0
Gueorgui Obregon

Avec Android Studio 1.4, le projet de modèle avec code de plaque de chaudière définit le thème Overlay sur votre AppbarLayout et/ou la barre d’outils. Ils sont également configurés pour être rendus derrière la barre d'état par fitSystemWindow attribut = true. Cela entraînera uniquement le rendu de la barre d'outils directement sous la barre d'état et tout le reste sous la barre d'outils. Les solutions fournies ci-dessus ne fonctionneront donc pas seules. Vous devrez apporter les modifications suivantes.

  • Supprimez le thème Superposition ou changez-le en thème non superposé pour la barre d'outils.
  • Mettez le code suivant dans votre styles-21.xml fichier.

    @Android: couleur/transparent

  • Attribuez ce thème à l'activité contenant le tiroir de navigation dans The AndroidManifest.xml file.

Cela rendra le tiroir de navigation à afficher derrière la barre d'état transparente.

0
Umer Farooq

La réponse acceptée a fonctionné pour moi en utilisant un CollapsingToolbarLayout. Il est important de noter cependant que setSytstemUiVisibility() remplace tous les appels précédents à cette fonction. Ainsi, si vous utilisez cette fonction ailleurs pour la même vue, vous devez inclure les indicateurs View.SYSTEM_UI_FLAG_LAYOUT_STABLE et View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, sinon ils seront remplacés par le nouvel appel.

Ce fut le cas pour moi, et une fois que j’ai ajouté les deux drapeaux à l’autre endroit où j’appelais setSystemUiVisibility(), la réponse acceptée a parfaitement fonctionné.

0
cpgreen2