Barre d'état translucide/transparente + dispositif de coordination + barre D'outils + Fragment

j'ai la configuration suivante:

  • j'utilise AppCompat
  • MainActivity, qui est titulaire d'un fragment et a une barre d'outils, qui se cache lorsque le défilement vers le bas
  • Fragment avec RecyclerView
  • toutes les vues qui devraient s'adapter à l'écran ont la android:fitsSystemWindows="true" selon la disposition xml

le problème est, Je ne peux pas obtenir le statusbar transparent dans ce cas. Ce que je fais est le suivant:

  1. Créer de l'activité et de l'appel setContent
  2. ensuite, j'essaie d'ajuster l'activité pour obtenir programmatiquement 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 le paramètre dans l'activité ( @+id/frame_container ) par le fragment

le statusbar est de couleur unie dans ce cas, et le les vues ne sont pas établis en dessous... Pourquoi?

Ce que je veux

je veux une barre d'outils, qui est étalée de l'écran et se cache complètement tandis que le contenu sous cette barre d'outils devrait s'adapter à l'écran et être dessiné derrière la barre de navigation transparente.

Mises en page

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: /q/coordinatorlayout-appbarlayout-does-not-draw-toolbar-properly-37916/"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, 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>

EDITION Captures d'écran

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

  • Première capture D'écran: montre la barre d'outils, rien n'est scrolled
  • deuxième Screenshot: je viens de commencer à faire défiler => la barre d'outils devrait maintenant faire défiler
  • troisième Screenshot: le contenu principal doit maintenant défiler sous la barre de navigation...

à la fin, je vais bien sûr rendre la barre d'outils et la barre de navigation semi transparente pour un meilleur effet visuel...

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

20
demandé sur prom85 2016-01-13 11:27:22

7 réponses

tl;dr Set android:fitsSystemWindows="false" au moins jusqu'à la racine CoordinatorLayout et jusqu'au contenant intérieur du fragment, @frame_container .

cela pourrait ne pas être la solution finale (i.e. il pourrait y avoir d'autres fitsSystemWindows à changer) alors dites-moi si vous avez des problèmes.

pourquoi

quand il s'agit de la barre de statut, je pense à fitsSystemWindows comme ainsi:

  • fitsSystemWindows="false" : dessine la vue normalement, sous la barre d'état en raison des drapeaux de fenêtre que vous avez mis.
  • fitsSystemWindows="true" : dessine la vue normalement, sous la barre d'état en raison des drapeaux de fenêtre que vous avez mis, mais ajoute un rembourrage supérieur de sorte que le contenu est dessiné sous la barre d'état et ils ne se chevauchent pas.

en fait, à mon avis, Le le blanc que vous voyez n'est pas la couleur de la barre d'état, mais plutôt votre fond CoordinatorLayout . Cela est dû à fitsSystemWindows="true" sur le coordinateur: il dessine l'arrière-plan à l'ensemble de la fenêtre, mais ajoute le rembourrage supérieur au contenu de sorte que les vues internes ne sont pas couverts par la barre de statut.

Ce n'est pas ce que vous voulez. Votre contenu intérieur doit être couvert par la barre de statut, et donc vous devez mettre fitsSystemWindows="false" au coordinateur (pour qu'il ne s'applique pas le rembourrage supérieur) et probablement pour le contenu lui-même.

une fois que vous obtenez comment cela fonctionne, il est facile de déboguer et d'atteindre l'effet que vous recherchez . en fait, ce n'est pas le cas. Des années passent, mais je passe encore des heures à essayer de trouver la bonne combinaison fitsSystemWindows, parce que la plupart des vues (dans les bibliothèques de soutien au moins) outrepassent le comportement par défaut que j'ai indiqué ci-dessus, de façons qui ne sont généralement pas intuitives. Voir this post"" pour un petit guide sur la façon de l'utiliser.

57
répondu natario 2016-07-19 13:34:10

modifiez vos styles.xml (v21) , ajouter 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 changer le thème parent selon votre goût, mais maintenant déclarez ce thème dans votre AndroidManifest.fichier xml pour une activité particulière comme ceci :

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

cela permettra à votre contenu visible sous la barre d'action transparente.

utilisez maintenant ce qui suit pour aligner votre barre d'outils au-dessous de la barre D'État correctement, appelez ceci dans votre oncreate:

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

obtenir la hauteur statusbar 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;
}

supprimer les éléments suivants des étiquettes de mise en page de votre coordonnateur:

    android:fitsSystemWindows="true"

maintenant, afin de réduire votre barre d'outils ou de la Cacher, 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 soutien de conception, car elle est sans bogue:

    compile 'com.android.support:design:23.1.0'
5
répondu Udit Kapahi 2016-01-18 12:18:54

après avoir lu vos descriptions au sujet de votre question, j'ai pensé styles de Google Photos correspond à votre exigence.

OK, Il ya juste quelques conseils pour votre question. Après mon test, ça fonctionne.

  • si vous voulez afficher du contenu derrière la barre d'état, vous devez ajouter <item name="android:windowTranslucentStatus">true</item> dans votre style lorsque le niveau de version Android est plus grand que 19 (à savoir KitKat )
  • si vous voulez afficher du contenu derrière la barre de navigation, vous devez ajouter <item name="android:windowTranslucentNavigation">true</item> dans votre style lorsque le niveau de version Android est plus grand que 19 (à savoir KitKat )
  • si vous voulez cacher Toolbar en douceur lorsque le contenu est déroulé et pour montrer Toolbar en douceur lorsque le contenu est déroulé, vous besoin d'ajouter app:layout_collapseMode="parallax" dans votre Les attributs de Toolbar basés sur vos codes actuels.Bien sûr, vous coordination des besoins Toolbar avec CollapsingToolbarLayout CoordinatorLayout et AppBarLayout .
4
répondu SilentKnight 2016-09-26 02:17:00

comme certains utilisateurs l'ont dit, en réglant android:fitsSystemWindows="false" , la disposition se chevauchait en dessous de statusbar .

je l'ai résolu en mettant android:fitsSystemWindows="true" et dans CoordinatorLayout tag paramètre app:statusBarBackground="@android:color/transparent" .

1
répondu MHSFisher 2017-12-23 06:15:19

pour moi, la raison n'était pas qu'il n'a pas fonctionné en soi, mais que j'utilise la bibliothèque de tiroir de matériel de Mike Penz et cette bibliothèque utilise plein écran + offset + fond personnalisé derrière la barre d'outils donc j'ai dû résoudre le problème en respectant cette configuration spéciale...

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

0
répondu prom85 2016-01-26 06:48:12

j'ai eu le même problème et ma solution a été d'ajouter android: fitsSystemWindows= "true " à la 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
répondu Jorge Casariego 2016-08-22 21:34:47

j'ai eu des problèmes pertinents dépendent de android:fitsSystemWindows réglage. Une fois que la fausse: Des collations ont été tirées sous la barre de Navigation Une fois en vrai: La barre d'état n'avait aucun fond transparent

Solution était vraiment simple... Pour ajouter android:layout_marginBottom= "48dp".

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

barre de Navigation théorique devrait avoir la taille fixe "48dp", mais dans les versions futures potentiellement il peut changer (comme barre D'État obtenu plus mince en 1dp en Guimauve), je ne voudrais pas compter sur taille fixe. Mieux en plus obtenir et appliquer sur le temps d'exécution.

si vous utilisez Google Map comme moi, vous pouvez vouloir savoir la taille de la barre D'ActionBar/barre d'outils et la barre de navigation dans le temps d'exécution:

dans onCreate utiliser 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 tiroir etc mettez-les encapsuler le niveau de coordination à l'intérieur plutôt qu'à l'extérieur comme autrement il fera d'autres vues à l'intérieur plus court par le marginBottom

0
répondu Artur Ex 2017-01-20 23:08:31