webentwicklung-frage-antwort-db.com.de

Transluzent/Transparent-Statusleiste + CoordinatorLayout + Symbolleiste + Fragment

Ich habe folgendes Setup:

  • Ich verwende AppCompat
  • MainActivity, die ein Fragment enthält und über eine Symbolleiste verfügt, die beim Scrollen nach unten ausgeblendet wird
  • Fragment mit RecyclerView
  • alle Ansichten, die auf den Bildschirm passen sollen, haben im XML-Layout den entsprechenden Android:fitsSystemWindows="true"

Das Problem ist, ich kann die Statusleiste in diesem Fall nicht transparent machen. Was ich mache ist folgendes:

  1. Erstellen Sie die Aktivität und rufen Sie setContent auf
  2. Dann versuche ich, die Aktivität so anzupassen, dass sie programmgesteuert eine durchscheinende Symbolleiste erhält, wie folgt:

    @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. Ersetzen Sie den Platzhalter in der Aktivität (@+id/frame_container) durch das Fragment

Die Statusleiste ist in diesem Fall durchgefärbt und die Ansichten werden nicht darunter gezeichnet. Warum?

Was ich möchte

Ich möchte eine Symbolleiste, die vom Bildschirm gescrollt und vollständig ausgeblendet wird, während der Inhalt unter dieser Symbolleiste auf "Bild" passen und hinter die transparente Navigationsleiste gezeichnet werden soll.

Layouts

Hier ist meine Haupttätigkeit:

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

Und hier ist mein Fragment, das in die Haupttätigkeit gestellt wird:

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

Ich benutze ein helles/dunkles Basisthema und Thema alles von Hand (weil der Benutzer jede Farbe als Primär-/Akzentfarbe auswählen kann). Denken Sie also daran, dass die Symbolleiste weiß ist (Standardhintergrundfarbe und -farbe des Themas). Ich habe auch einen schwarzen Rand hinzugefügt, damit Sie sehen, wo die Aktivität endet ...

  • Erster Screenshot: Zeigt die Symbolleiste an, nichts wird gescrollt
  • Zweiter Screenshot: Ich habe gerade angefangen zu scrollen => Die Symbolleiste sollte jetzt weg scrollen
  • Dritter Screenshot: Der Hauptinhalt sollte jetzt unter der Navigationsleiste angezeigt werden ...

Am Ende werde ich natürlich die Symbolleiste und die Navigationsleiste halb transparent machen, um einen besseren visuellen Effekt zu erzielen ...

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

21
prom85

Für mich war der Grund nicht, dass es nicht per se funktionierte, sondern dass ich die Materialschubladen-Bibliothek von Mike Penz benutze und diese Bibliothek verwendet Vollbild + Offset + benutzerdefinierten Hintergrund hinter der Symbolleiste, sodass ich das Problem unter Berücksichtigung dieses speziellen Problems lösen musste Konfiguration...

Ich werde die Punkte für die meiner Meinung nach informativste Antwort belohnen ...

1
prom85

tl; dr Setzt Android:fitsSystemWindows="false" mindestens auf das Stammverzeichnis CoordinatorLayout und auf den inneren Fragmentcontainer @frame_container.

Dies ist möglicherweise nicht die endgültige Lösung (d. H., Es gibt möglicherweise noch andere fitsSystemWindows-Werte, die geändert werden müssen). Sagen Sie mir also, wenn Sie Probleme haben.

Warum

Wenn es um die Statusleiste geht, denke ich an fitsSystemWindows:

  • fitsSystemWindows="false": Zeichnet die Ansicht normal, unter der Statusleiste aufgrund der von Ihnen gesetzten Fensterflags.
  • fitsSystemWindows="true": Zeichnet die Ansicht normal, unter aufgrund der von Ihnen festgelegten Fenstermarkierungen unter der Statusleiste, aber fügt eine obere Auffüllung hinzu, sodass der Inhalt unter der Statusleiste angezeigt wird und sich nicht überlappt.

Meines Erachtens ist das Weiß, das Sie sehen, nicht die Farbe der Statusleiste, sondern Ihr CoordinatorLayout-Hintergrund. Dies liegt an fitsSystemWindows="true" am Koordinator: Er zeichnet den Hintergrund des gesamten Fensters, fügt jedoch den Inhalt mit einem Top-Abstand hinzu, sodass innere Ansichten nicht durch die Statusleiste verdeckt werden.

Das wollen Sie nicht. Ihr innerer Inhalt muss muss in der Statusleiste verdeckt sein, und Sie müssen fitsSystemWindows="false" auf den Koordinator setzen (damit keine Auffüllung erfolgt) und wahrscheinlich auf den Inhalt selbst.

Sobald Sie wissen, wie es funktioniert, es ist einfach zu debuggen und die gewünschte Wirkung zu erzielen. Eigentlich ist es nicht. Jahre vergehen, aber ich versuche immer noch, die richtige Kombination von FitsSystemWindows herauszufinden, da die meisten Views (zumindest in den Support-Bibliotheken) das oben erwähnte Standardverhalten überschreiben meistens nicht intuitiv. Siehe diesen Beitrag für eine kleine Anleitung, wie man es benutzt.

60
natario

Bearbeiten Sie Ihre styles.xml (v21) und fügen Sie den folgenden Stil hinzu

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

Sie können das übergeordnete Design nach Ihren Wünschen ändern, aber jetzt deklarieren Sie dieses Design in Ihrer AndroidManifest.xml-Datei für eine bestimmte Aktivität wie diese:

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

Dadurch wird Ihr Inhalt unter der transparenten Aktionsleiste sichtbar.

Richten Sie nun die Symbolleiste korrekt unter der Statusleiste aus. Rufen Sie dies in Ihrem oncreate auf:

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

Rufen Sie die Höhe der Statusleiste auf:

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

Entfernen Sie folgende Elemente aus den Layout-Tags Ihres Koordinators:

    Android:fitsSystemWindows="true"

Um die Symbolleiste auszublenden oder auszublenden, können Sie sich auf das folgende Tutorial beziehen:

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

Stellen Sie sicher, dass Sie die folgende Version der Design-Support-Bibliothek verwenden, da sie fehlerfrei ist:

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

Nachdem ich Ihre Beschreibungen zu Ihrer Frage gelesen hatte, dachte ich, dass Stile von Google Photos Ihren Anforderungen entsprechen.

OK, es gibt nur einige Tipps für Ihre Frage. Nach meinem Test funktioniert es.

  • Wenn Sie Inhalte hinter der Statusleiste anzeigen möchten, müssen Sie <item name="Android:windowTranslucentStatus">true</item> In Ihren Stil einfügen, wenn Android Versionslevel größer als 19 ist (nämlich KitKat)
  • Wenn Sie Inhalte hinter der Navigationsleiste anzeigen möchten, müssen Sie <item name="Android:windowTranslucentNavigation">true</item> In Ihren Stil einfügen, wenn Android Versionslevel größer als 19 ist (nämlich KitKat)
  • Wenn Sie Toolbar beim Scrollen von Inhalten reibungslos ausblenden und Toolbar beim Scrollen von Inhalten reibungslos anzeigen möchten, müssen Sie app:layout_collapseMode="parallax" Zu den Attributen von Toolbar hinzufügen, basierend auf Ihren aktuellen Codes. Natürlich benötigen Sie Koordinaten Toolbar mit CollapsingToolbarLayoutCoordinatorLayout und AppBarLayout.
4
SilentKnight

wie einige Benutzer sagten, durch die Einstellung von Android:fitsSystemWindows="false", das Layout überlappt unter statusbar.

Ich habe es gelöst, indem ich Android:fitsSystemWindows="true" und in CoordinatorLayout Tag-Einstellung app:statusBarBackground="@Android:color/transparent" eingestellt habe.

1
MHSFisher

Ich hatte relevante Probleme von Android abhängig: passtSystemWindows-Einstellung . Einmal falsch: Snacks wurden unter der Navigationsleiste gezeichnet Einmal wahr: Statusleiste hatte keinen transparenten Hintergrund

Die Lösung war wirklich einfach ....__ Um nur Android hinzuzufügen: layout_marginBottom = "48dp". zu CoordinatorLayout wie das:

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

Theoretisch sollte die Navigationsleiste eine feste Größe von "48dp" haben, aber in zukünftigen Versionen kann sich dies möglicherweise ändern (z. B. wenn die Statusleiste in Marshmallow um 1 dB verringert wurde), so dass ich mich nicht auf eine feste Größe verlassen würde zur Laufzeit.

Wenn Sie Google Map wie mich verwenden, möchten Sie möglicherweise die Größe der ActionBar/Toolbar und die Navigationsleiste zur Laufzeit kennen:

verwenden Sie in onCreate diesen 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;
                    }
                }
        );

Und was ist wichtig? Wenn Sie zusätzliche Ebenen wie die Schublade usw. erhalten haben, kapseln Sie das CoordinatorLayout nach innen und nicht nach außen, da andernfalls andere Ansichten innerhalb um den unteren Rand gekürzt werden

0
Artur Ex

Ich hatte das gleiche Problem und meine Lösung war Android: passtSystemWindows = "true" zum 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