web-dev-qa-db-fra.com

Barre d'état Translucide/Transparent + CoordinatorLayout + Toolbar + Fragment

J'ai la configuration suivante:

  • J'utilise AppCompat
  • MainActivity, qui contient un fragment et une barre d’outils, qui se cache lors du défilement
  • Fragment avec RecyclerView
  • toutes les vues devant correspondre à l'écran ont le Android:fitsSystemWindows="true" correspondant dans la mise en page xml

Le problème est que je ne peux pas obtenir la barre d'état transparente dans ce cas. Ce que je fais est la suivante:

  1. Créez l'activité et appelez setContent
  2. Ensuite, j'essaie d'ajuster l'activité pour obtenir par programme une barre d'outils translucide comme suit:

    @TargetApi(Build.VERSION_CODES.Lollipop)
    public void themeNavAndStatusBar(Activity activity)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop)
            return;
    
        Window w = activity.getWindow();
        w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        w.setNavigationBarColor(activity.getResources().getColor(Android.R.color.transparent));
    
        w.setStatusBarColor(activity.getResources().getColor(Android.R.color.transparent));
    }
    
  3. Remplacer l'espace réservé dans l'activité (@+id/frame_container) par le fragment

Dans ce cas, la barre d'état est de couleur unie et les vues ne sont pas dessinées en dessous ... Pourquoi?

Ce que je veux

Je veux une barre d’outils qui défile à l’écran et se cache complètement tandis que le contenu situé sous cette barre d’outils doit tenir dans Écran et être dessiné derrière la barre de navigation transparente.

Layouts

Voici mon activité principale:

<Android.support.design.widget.CoordinatorLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/clMain"
    Android:fitsSystemWindows="true"
    Android:background="?attr/main_background_color"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/appBarLayout"
        Android:fitsSystemWindows="true"
        Android:background="@null"
        app:elevation="0dp"
        app:contentInsetLeft="0dp"
        app:contentInsetStart="0dp"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            Android:background="?attr/colorPrimary"
            Android:elevation="4dp"
            Android:theme="?actionBarThemeStyle"
            app:popupTheme="?actionBarPopupThemeStyle"
            app:layout_scrollFlags="scroll|enterAlways">

            <LinearLayout
                Android:orientation="vertical"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content">

                <LinearLayout
                    Android:orientation="horizontal"
                    Android:layout_width="wrap_content"
                    Android:layout_height="wrap_content">

                    <ImageView
                        Android:id="@+id/ivToolbarDataSource"
                        Android:layout_gravity="center_vertical"
                        Android:layout_marginRight="2dp"
                        Android:layout_width="24dp"
                        Android:layout_height="24dp" />

                    <TextView
                        Android:id="@+id/tvToolbarTitle"
                        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                        Android:theme="?actionBarThemeStyle"
                        Android:layout_gravity="center_vertical"
                        Android:layout_width="wrap_content"
                        Android:layout_height="wrap_content" />

                </LinearLayout>

                <TextView
                    Android:id="@+id/tvToolbarSubTitle"
                    style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
                    Android:theme="?actionBarThemeStyle"
                    Android:layout_width="wrap_content"
                    Android:layout_height="wrap_content" />

            </LinearLayout>



        </Android.support.v7.widget.Toolbar>

        <!-- BUG: http://stackoverflow.com/questions/30541409/coordinatorlayoutappbarlayout-does-not-draw-toolbar-properly -->
        <View
            Android:layout_width="fill_parent"
            Android:layout_height="1dp"/>

    </Android.support.design.widget.AppBarLayout>

    <FrameLayout
        Android:id="@+id/frame_container"
        Android:fitsSystemWindows="true"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="bottom|right"
        Android:layout_margin="32dp"
        Android:src="@drawable/ic_local_offer_white_24dp"
        app:backgroundTint="?attr/colorPrimary"
        app:borderWidth="0dp"
        app:fabSize="normal"
        app:rippleColor="?attr/colorPrimaryDark"
        app:layout_anchorGravity="bottom|right|end"
        app:layout_behavior="com.test.classes.ScrollAwareFABBehavior"/>

</Android.support.design.widget.CoordinatorLayout>

Et voici mon fragment, qui sera placé dans l'activité principale:

<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:fitsSystemWindows="true"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.v4.widget.SwipeRefreshLayout
        Android:id="@+id/srlImages"
        Android:fitsSystemWindows="true"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <Android.support.v7.widget.RecyclerView
            Android:id="@+id/rvImages"
            Android:fitsSystemWindows="true"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />

    </Android.support.v4.widget.SwipeRefreshLayout>

    <TextView
        Android:id="@+id/tvEmpty"
        Android:gravity="center"
        Android:layout_centerInParent="true"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

</RelativeLayout>

EDIT - Captures d'écran

J'utilise un thème de base clair/foncé et tout le thème à la main (car l'utilisateur peut sélectionner n'importe quelle couleur comme couleur primaire/accent), alors ne vous gênez pas pour que la barre d'outils soit blanche (c'est la couleur d'arrière-plan et la couleur primaire du thème par défaut). J'ai aussi ajouté une bordure noire pour que vous puissiez voir où l'activité se termine ...

  • Première capture d'écran: affiche la barre d'outils, rien ne défile
  • Deuxième capture d'écran: je viens de commencer à faire défiler => la barre d'outils doit maintenant défiler
  • Troisième capture d'écran: le contenu principal doit maintenant défiler sous la barre de navigation ...

Au final, je vais bien sûr rendre la barre d’outils et la barre de navigation semi-transparentes pour un meilleur effet visuel ...

 enter image description here  enter image description here  enter image description here

21
prom85

Pour moi, la raison n’est pas que cela n’a pas fonctionné en tant que tel, mais que j’utilise la bibliothèque de tiroirs du matériel de Mike Penz et que cette bibliothèque utilise le fond plein écran + offset + personnalisé derrière la barre d’outils. installer...

Je vais récompenser les points à la réponse la plus informative à mon avis si ...

1
prom85

tl; dr Définissez Android:fitsSystemWindows="false" au moins à la racine CoordinatorLayout et au conteneur de fragment interne, @frame_container.

Cela pourrait ne pas être la solution finale (c’est-à-dire qu’il pourrait y avoir une autre fitsSystemWindows à changer), alors dites-moi si vous avez des problèmes.

Pourquoi

En ce qui concerne la barre d’état, je pense à fitsSystemWindows comme ceci:

  • fitsSystemWindows="false": dessine la vue normalement, sous la barre d'état en raison des indicateurs de fenêtre que vous avez définis.
  • fitsSystemWindows="true": dessine la vue normalement, sous dans la barre d'état en raison des indicateurs de fenêtre que vous avez définis, mais ajoute un remplissage supérieur afin que le contenu soit dessiné sous la barre d'état et ne se chevauche pas.

En fait, à mon avis, le blanc que vous voyez n'est pas la couleur de la barre d'état, mais plutôt votre arrière-plan CoordinatorLayout. Cela est dû à fitsSystemWindows="true" sur le coordinateur: il dessine l'arrière-plan sur toute la fenêtre, mais ajoute un remplissage supérieur au contenu afin que les vues intérieures ne soient pas couvertes par la barre d'état.

Ce n'est pas ce que tu veux. Votre contenu interne doit être couvert par la barre d'état. Vous devez donc définir fitsSystemWindows="false" sur le coordinateur (pour qu'il n'applique pas le remplissage supérieur) et probablement sur le contenu lui-même.

Une fois que vous avez compris comment cela fonctionne, il est facile de déboguer et d'obtenir l'effet que vous recherchez. En fait, ce n'est pas le cas. Des années ont passé, mais je passe encore des heures à essayer de trouver la bonne combinaison système, car la plupart des vues (au moins dans les bibliothèques de support) remplacent le comportement par défaut que j'ai indiqué La plupart du temps, ce n’est pas intuitif. Voir cet article pour un petit guide sur son utilisation.} _

60
natario

Éditez votre styles.xml (v21), ajoutez le style suivant

 <style name="AppTheme.Home" parent="AppTheme.Base">
    <!-- Customize your theme here. -->
    <item name="Android:windowTranslucentStatus">true</item>
    <item name="Android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="Android:windowTranslucentNavigation">true</item>

</style>

Vous pouvez modifier le thème parent selon vos préférences, mais déclarez maintenant ce thème dans votre fichier AndroidManifest.xml pour une activité particulière comme celle-ci:

 <activity
        Android:theme="@style/AppTheme.Home"
        Android:name=".HomeActivity"
        Android:launchMode="singleTop"
        Android:screenOrientation="portrait" />

Cela laissera votre contenu visible sous la barre d’action transparente.

Maintenant, utilisez ce qui suit pour aligner correctement votre barre d’outils sous la StatusBar, appelez ceci dans votre oncreate:

 toolbar.setPadding(0, getStatusBarHeight(), 0, 0);

Obtenez la hauteur de la barre d'état en utilisant ce qui suit:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "Android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Supprimez les éléments suivants de vos balises de présentation de coordinateur:

    Android:fitsSystemWindows="true"

Maintenant, afin de réduire votre barre d’outils ou de la masquer, vous pouvez vous référer au tutoriel suivant:

http://antonioleiva.com/collapsing-toolbar-layout/

Assurez-vous que vous utilisez la version suivante de la bibliothèque de support de conception, car elle n’a pas de bogue:

    compile 'com.Android.support:design:23.1.0'
7
Udit Kapahi

Après avoir lu vos descriptions de votre question, je pensais que les styles de Google Photos correspondaient à vos besoins. 

OK, il y a juste quelques astuces pour votre question. Après mon test, ça marche.

  • Si vous souhaitez afficher le contenu derrière la barre d'état, vous devez ajouter <item name="Android:windowTranslucentStatus">true</item> à votrestyle lorsque le niveau de version Android est supérieur à 19 (à savoir KitKat ).
  • Si vous souhaitez afficher le contenu derrière la barre de navigation, vous devez ajouter <item name="Android:windowTranslucentNavigation">true</item> à votrestyle lorsque le niveau de version Android est supérieur à 19 (à savoir KitKat ).
  • Si vous souhaitez masquer Toolbar en douceur lorsque le contenu défile vers le haut .__ et afficher Toolbar en douceur lorsque vous faites défiler le contenu, vous devez ajouter app:layout_collapseMode="parallax" à vos attributs de Toolbar en fonction de vos codes actuels. Bien sûr, vous avez besoin de coordonner Toolbar avec CollapsingToolbarLayoutCoordinatorLayout et AppBarLayout.
4
SilentKnight

comme certains utilisateurs l'ont dit, en définissant Android:fitsSystemWindows="false", la disposition chevauchant en dessous de statusbar.

Je l'ai résolu en définissant Android:fitsSystemWindows="true" et en CoordinatorLayout paramètre de balise app:statusBarBackground="@Android:color/transparent".

1
MHSFisher

J'avais des problèmes pertinents qui dépendaient d'Android: paramètre fitsSystemWindows . Once false: Des collations ont été dessinées sous la barre de navigation

La solution était très simple .... Juste pour ajouter Android: layout_marginBottom = "48dp". à CoordinatorLayout comme ça:

just to add <Android.support.design.widget.CoordinatorLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
xmlns:map="http://schemas.Android.com/apk/res-auto"
tools:context=".MapsActivity"
Android:id="@+id/coordinatorLayout"
Android:layout_width="match_parent"
Android:layout_height="match_parent"

Android:fitsSystemWindows="false"
Android:layout_marginBottom="48dp">

Théoriquement, la barre de navigation devrait avoir une taille fixe «48dp», mais elle pourrait éventuellement changer dans les versions futures (comme la barre d'état est devenue plus fine de 1 dp en Marshmallow), je ne m'appuierais donc pas sur la taille fixe ... sur le temps d'exécution.

Si vous utilisez Google Map comme moi, vous voudrez peut-être connaître la taille de la barre d’action/barre d’outils et la barre de navigation au moment de l’exécution:

dans onCreate, utilisez ce code:

            final TypedArray styledAttributes = MapsActivity.this.getTheme().obtainStyledAttributes(
                new int[]{Android.R.attr.actionBarSize});
        mToolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();
        // translucent bars code. Will not fire below Lollipop
        // Ask NavigationBar Height
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.coordinatorLayout),
                new OnApplyWindowInsetsListener() { // setContentView() must be fired already
                    @Override
                    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                        statusBar = insets.getSystemWindowInsetTop(); // You may also need this value
                        mNavBarHeight = insets.getSystemWindowInsetBottom();
                        if (mMap != null)
                            mMap.setPadding(0, mToolbarHeight, 0, mNavBarHeight);
                        // else will be set in onMapReady()
                        SharedPreferences.Editor editor = mSharedPref.edit();
                        editor
                                .putInt(NAVBAR_HEIGHT_KEY, mNavBarHeight)
                                .commit(); // Save the results in flash memory and run the code just once on app first run instead of doing it every run
                        return insets;
                    }
                }
        );

Et ce qui est important Si vous avez des couches supplémentaires comme un tiroir, etc., placez-les encapsulant le CoordinatorLayout à l'intérieur plutôt qu'à l'extérieur, sinon les autres vues à l'intérieur seraient plus courtes de la part marginBottom.

0
Artur Ex

J'avais le même problème et ma solution était d'ajouter Android: fitsSystemWindows = "true" au DrawerLayout

<Android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true"> 

....

</Android.support.v4.widget.DrawerLayout>
0
Jorge Casariego