Wie verwende ich DrawerLayout, um über der Aktionsleiste / Symbolleiste und unter der Statusleiste anzuzeigen?

394

Ich habe in der neuen Side Nav-Spezifikation für Materialdesign gesehen, dass Sie die Schublade über der Aktionsleiste und hinter der Statusleiste anzeigen können. Wie kann ich das umsetzen?

Chris Banes
quelle
4
Bis heute gibt es keine klare Antwort, die mit Abwärtskompatibilität funktioniert. Diese Art von Problemen ärgert jeden Programmierer wirklich. Bereits Werbung für die "N" -API und viele grundlegende Aspekte zur Verbesserung des Android-Systems.
Val Martinez

Antworten:

528

Neue Funktionen im Framework und Support-Bibliotheken ermöglichen genau dies. Es gibt drei "Puzzleteile":

  1. Verwenden der Symbolleiste, damit Sie Ihre Aktionsleiste in Ihre Ansichtshierarchie einbetten können.
  2. Herstellung DrawerLayout fitsSystemWindows so dass es hinter den Systemschienen verlegt geführt wird.
  3. Deaktivieren Sie Theme.Materialdie normale Farbe der Statusleiste, damit DrawerLayout stattdessen dort zeichnen kann.

Ich gehe davon aus, dass Sie den neuen Appcompat verwenden werden.

Zunächst sollte Ihr Layout folgendermaßen aussehen:

<!-- The important thing to note here is the added fitSystemWindows -->
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/my_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Your normal content view -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- We use a Toolbar so that our drawer can be displayed
             in front of the action bar -->
        <android.support.v7.widget.Toolbar  
            android:id="@+id/my_awesome_toolbar"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:minHeight="?attr/actionBarSize"
            android:background="?attr/colorPrimary" />

        <!-- The rest of your content view -->

    </LinearLayout>

    <!-- Your drawer view. This can be any view, LinearLayout
         is just an example. As we have set fitSystemWindows=true
         this will be displayed under the status bar. -->
    <LinearLayout
        android:layout_width="304dp"
        android:layout_height="match_parent"
        android:layout_gravity="left|start"
        android:fitsSystemWindows="true">

        <!-- Your drawer content -->

    </LinearLayout>

</android.support.v4.widget.DrawerLayout>

Dann in Ihrer Aktivität / Fragment:

public void onCreate(Bundled savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Your normal setup. Blah blah ...

    // As we're using a Toolbar, we should retrieve it and set it
    // to be our ActionBar
    Toolbar toolbar = (...) findViewById(R.id.my_awesome_toolbar);
    setSupportActionBar(toolbar);

    // Now retrieve the DrawerLayout so that we can set the status bar color.
    // This only takes effect on Lollipop, or when using translucentStatusBar
    // on KitKat.
    DrawerLayout drawerLayout = (...) findViewById(R.id.my_drawer_layout);
    drawerLayout.setStatusBarBackgroundColor(yourChosenColor);
}

Dann müssen Sie sicherstellen, dass das DrawerLayout hinter der Statusleiste sichtbar ist. Sie tun dies, indem Sie Ihr Werte-v21-Thema ändern:

values-v21 / theme.xml

<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

Hinweis: Wenn a <fragment android:name="fragments.NavigationDrawerFragment">anstelle von verwendet wird

<LinearLayout
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true">

    <!-- Your drawer content -->

</LinearLayout>

Im tatsächlichen Layout wird der gewünschte Effekt erzielt, wenn Sie fitsSystemWindows(boolean)eine Ansicht aufrufen , die Sie von der onCreateViewMethode zurückgeben.

@Override
public View onCreateView(LayoutInflater inflater, 
                         ViewGroup container,
                         Bundle savedInstanceState) {
    View mDrawerListView = inflater.inflate(
        R.layout.fragment_navigation_drawer, container, false);
    mDrawerListView.setFitsSystemWindows(true);
    return mDrawerListView;
}
Chris Banes
quelle
3
Ja, das DrawerLayoutmuss hinter den Systemstangen angeordnet werden. Sie müssen es dann in der Schubladenansicht so einstellen, dass DrawerLayoutes in den Fenstereinlagen angeordnet ist.
Chris Banes
11
Kann das überhaupt nicht zum Laufen bringen. Mit dem obigen Code in einer neuen Demo-Anwendung ähnelt das Ergebnis dem, was @ScootrNova beschreibt. Siehe diesen Screenshot: imgur.com/QLk3syt
Michael Schmidt
6
Sieht so aus, als müssten Sie layout_marginTopim Stammverzeichnis Ihres Schubladeninhalts tatsächlich ein Negativ verwenden . Andernfalls wird der Hintergrund des Layouts Ihres Schubladeninhalts über der Statusleiste gezeichnet und alles andere wird nach unten gedrückt. Dies scheint jedoch eine ziemlich grobe Lösung zu sein, soweit ich weiß, gibt es keine? Attr / statusBarSize oder ähnliches von Android.
Charles Madere
26
Um den Effekt zu erzielen, bei dem die Schublade in der Statusleiste sichtbar ist, habe ich android: fitSystemWindows im DrawerLayout auf false gesetzt, android: fitSystemWindows in meinem Hauptinhaltslayout (dem Layout mit der Symbolleiste) auf true gesetzt und <Elementname hinzugefügt = "android: windowTranslucentStatus"> true </ item> zu meinem Thema - auf Lollipop also
Jakob
8
Diese Antwort ist unvollständig. Sie müssen Ihre Navigationsschublade auch in ein ScrimLayout einwickeln. Siehe stackoverflow.com/a/26926998/174149
Markus Hi
138

BEARBEITEN: Die neue Design Support Library unterstützt dies und die vorherige Methode ist nicht mehr erforderlich.

Dies kann jetzt mit der neuen Android Design Support Library erreicht werden .

Sie können die Cheesesquare-Beispiel-App von Chris Banes sehen, die alle neuen Funktionen demonstriert .


Vorherige Methode:

Da es keine vollständige Lösung gibt, habe ich hier das gewünschte Ergebnis erzielt.

Fügen Sie zunächst ein ScrimInsetsFrameLayout in Ihr Projekt ein.

/*
* Copyright 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* A layout that draws something in the insets passed to 
* {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome
* (status and navigation bars, overlay action bars).
*/
public class ScrimInsetsFrameLayout extends FrameLayout {
    private Drawable mInsetForeground;

    private Rect mInsets;
    private Rect mTempRect = new Rect();
    private OnInsetsCallback mOnInsetsCallback;

    public ScrimInsetsFrameLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public ScrimInsetsFrameLayout(
        Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.ScrimInsetsView, defStyle, 0);
        if (a == null) {
            return;
        }
        mInsetForeground = a.getDrawable(
            R.styleable.ScrimInsetsView_insetForeground);
        a.recycle();

        setWillNotDraw(true);
    }

    @Override
    protected boolean fitSystemWindows(Rect insets) {
        mInsets = new Rect(insets);
        setWillNotDraw(mInsetForeground == null);
        ViewCompat.postInvalidateOnAnimation(this);
        if (mOnInsetsCallback != null) {
            mOnInsetsCallback.onInsetsChanged(insets);
        }
        return true; // consume insets
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        int width = getWidth();
        int height = getHeight();
        if (mInsets != null && mInsetForeground != null) {
            int sc = canvas.save();
            canvas.translate(getScrollX(), getScrollY());

            // Top
            mTempRect.set(0, 0, width, mInsets.top);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Bottom
            mTempRect.set(0, height - mInsets.bottom, width, height);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Left
            mTempRect.set(
                0, 
                mInsets.top, 
                mInsets.left, 
                height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            // Right
            mTempRect.set(
                width - mInsets.right, 
                mInsets.top, width, 
                height - mInsets.bottom);
            mInsetForeground.setBounds(mTempRect);
            mInsetForeground.draw(canvas);

            canvas.restoreToCount(sc);
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (mInsetForeground != null) {
            mInsetForeground.setCallback(this);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mInsetForeground != null) {
            mInsetForeground.setCallback(null);
        }
    }

    /**
     * Allows the calling container to specify a callback for custom 
     * processing when insets change (i.e. when {@link #fitSystemWindows(Rect)}
     * is called. This is useful for setting padding on UI elements 
     * based on UI chrome insets (e.g. a Google Map or a ListView). 
     * When using with ListView or GridView, remember to set
     * clipToPadding to false.
     */
    public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) {
        mOnInsetsCallback = onInsetsCallback;
    }

    public static interface OnInsetsCallback {
        public void onInsetsChanged(Rect insets);
    }
}

Erstellen Sie dann ein Styleable, damit das eingestellt werden insetForegroundkann.

values ​​/ attrs.xml

<declare-styleable name="ScrimInsetsView">
    <attr name="insetForeground" format="reference|color" />
</declare-styleable>

Aktualisieren Sie die XML-Datei Ihrer Aktivität und stellen Sie sicher, dass android:fitsSystemWindowssowohl auf DrawerLayoutals auch auf true gesetzt ist ScrimInsetsFrameLayout.

layout / activity_main.xml

<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <!-- The main content view -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- Your main content -->

    </LinearLayout>

    <!-- The navigation drawer -->
    <com.example.app.util.ScrimInsetsFrameLayout 
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/scrimInsetsFrameLayout"
        android:layout_width="320dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        app:insetForeground="#4000">

        <!-- Your drawer content -->

    </com.example.app.util.ScrimInsetsFrameLayout>

</android.support.v4.widget.DrawerLayout>

Legen Sie innerhalb der onCreate-Methode Ihrer Aktivität die Hintergrundfarbe der Statusleiste im Schubladenlayout fest.

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ...

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
    mDrawerLayout.setStatusBarBackgroundColor(
        getResources().getColor(R.color.primary_dark));
}

Aktualisieren Sie abschließend das Thema Ihrer App so, dass DrawerLayoutes sich hinter der Statusleiste befindet.

values-v21 / styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Ergebnis:

Suyash
quelle
10
Das hat bei mir am besten funktioniert. Ich habe 2 Tage damit verbracht, dieses Ding zum Laufen zu bringen, und das ist das eine. Dies sollte als Antwort markiert werden. Ich danke dir sehr.
Kalehv
2
Ich benutze kein Appcompat und das hat nicht funktioniert. :( Gibt es eine Anleitung, die dies ohne Appcompat zum Laufen bringt?
Jared Rummler
3
Dies ist die perfekteste Antwort. Ich habe es auf verschiedenen Android-Geräten von 4.X bis 5.X implementiert und getestet und kann bestätigen, dass es perfekt funktioniert. Vielen Dank.
Aritra Roy
2
Wie gesagt, es funktioniert perfekt, aber ich habe ein kleines Problem. Die Aktivität mit der Navigationsleiste hat die transparente Statusleiste, aber alle anderen Aktivitäten haben die Farbe "primaryDark" in der Statusleiste verloren. Wie bekomme ich das zurück?
Aritra Roy
5
Ich habe drei Tage gebraucht, um zu akzeptieren, dass es derzeit keinen anderen Weg gibt, als dieses zusätzliche Layout zu verwenden, das um das Schubladenfragment gewickelt ist. Andernfalls ist die Statusleiste entweder grau (Hintergrundfarbe des ersten Kindes) oder die Schublade wird unter der Statusleiste angezeigt.
Denis Loh
96

Mit der Veröffentlichung der neuesten Android Support Library (Version 22.2.0) haben wir eine Design Support Library und als Teil eine neue Ansicht namens NavigationView . Anstatt alles alleine mit ScrimInsetsFrameLayoutall den anderen Dingen zu machen, verwenden wir einfach diese Ansicht und alles ist für uns erledigt.

Beispiel

Schritt 1

Fügen Sie das Design Support LibraryIhrer build.gradleDatei hinzu

dependencies {
    // Other dependencies like appcompat
    compile 'com.android.support:design:22.2.0'
}

Schritt 2

Fügen Sie das NavigationViewzu Ihrem hinzu DrawerLayout:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true"> <!-- this is important -->

     <!-- Your contents -->

     <android.support.design.widget.NavigationView
         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:menu="@menu/navigation_items" /> <!-- The items to display -->
 </android.support.v4.widget.DrawerLayout>

Schritt 3

Erstellen Sie eine neue Menü-Ressource in /res/menuund fügen Sie die Elemente und Symbole hinzu, die Sie anzeigen möchten:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_action_home"
            android:title="Home" />
        <item
            android:id="@+id/nav_example_item_1"
            android:icon="@drawable/ic_action_dashboard"
            android:title="Example Item #1" />
    </group>

    <item android:title="Sub items">
        <menu>
            <item
                android:id="@+id/nav_example_sub_item_1"
                android:title="Example Sub Item #1" />
        </menu>
    </item>

</menu>

Schritt 4

Starten Sie die Navigationsansicht und behandeln Sie Klickereignisse:

public class MainActivity extends AppCompatActivity {

    NavigationView mNavigationView;
    DrawerLayout mDrawerLayout;

    // Other stuff

    private void init() {
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                mDrawerLayout.closeDrawers();
                menuItem.setChecked(true);
                switch (menuItem.getItemId()) {
                    case R.id.nav_home:
                        // TODO - Do something
                        break;
                    // TODO - Handle other items
                }
                return true;
            }
        });
    }
}

Schritt 5

Achten Sie darauf, Satz android:windowDrawsSystemBarBackgroundsund android:statusBarColorin values-v21sonst Ihre Schublade gewann `t angezeigt werden„unter“der StatusBar

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Other attributes like colorPrimary, colorAccent etc. -->
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Optionaler Schritt

Fügen Sie der Navigationsansicht eine Kopfzeile hinzu. Dazu erstellen Sie einfach ein neues Layout und fügen app:headerLayout="@layout/my_header_layout"es der Navigationsansicht hinzu.

Ergebnis

Bild mit Navigationsansicht

Anmerkungen

  • Die hervorgehobene Farbe verwendet die über das colorPrimaryAttribut definierte Farbe
  • Die Listenelemente verwenden die über das Attribut definierte FarbetextColorPrimary
  • Die Symbole verwenden die über das Attribut definierte FarbetextColorSecondary

Sie können auch die Beispiel-App von Chris Banes überprüfen, die die Navigationsansicht zusammen mit den anderen neuen Ansichten, die Teil der Design Support Library sind (wie FloatingActionButton , TextInputLayout , Snackbar , TabLayout usw.) , hervorhebt .

umkehren
quelle
1
danke @reVerse !!. > Wenn Sie jedes Element und Symbol in der Liste aus den Stildateien aktualisieren möchten, können Sie dies tun mit:<item name="itemTextColor">@color/YOUR_COLOR</item> <item name="itemIconTint">@color/YOUR_COLOR</item>
Juan Saravia
Wie ändern Sie die Hintergrundfarbe des ausgewählten Elements?
Joop
2
Dieser Ansatz erzeugt weiterhin die Navigationsansicht, die sich hinter der Aktionsleiste befindet.
Southton
1
@southerton natürlich müssen Sie ein Toolbar- es gibt keine Möglichkeit, dies mit einemActionBar
reVerse
1
@ reegan29 Rufen mDrawerLayout.openDrawer(GravityCompat.START);Sie einfach an, wo immer Sie wollen. Wenn Sie einen verwenden, ActionBarDrawerTogglesollte dies automatisch erfolgen, sobald Sie auf das Hamburger-Symbol klicken.
ReVerse
6

Damit es funktioniert, muss in values-v21-Stilen oder Theme-XML dieses Attribut verwendet werden:

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

Das macht die Magie!

Nicolas Jafelle
quelle
3
Dadurch wird meine Aktionsleiste auch hinter der Statusleiste angezeigt.
Michiel
Aber das ist der Effekt, den wir erreichen wollen. Schauen Sie sich die Google Mail 5.0-App an. Es zeigt die Seitenleiste hinter der Statusleiste.
Nicolas Jafelle
Das wollte ich nicht sagen. Obwohl sich die Navigationsleiste mit dieser Codezeile hinter der Statusleiste befindet, befindet sich auch die Symbolleiste / Aktionsleiste.
Michiel
2
Das Poster und der Antwortende ist ein Google-Mitarbeiter, der AppCompat entwickelt hat. Ich bin mir also ziemlich sicher, dass er wusste, was er tat, als er den Inhalt schrieb.
Afollestad
@Mixx, Sie können android: fitSystemWindows = "true" für Ihre normale Inhaltsansicht festlegen (wenn Sie beispielsweise das akzeptierte Antwortlayout verwenden). Es kann sogar für Android 4.4 funktionieren. Hier gibt es jedoch einen kleinen Unterschied: In Android 5.0 ist die Transparenzstufe in der Statusleiste etwas höher (höherer Alpha-Wert) als in GMail, wodurch die Statusleiste noch dunkler wird.
Qianqian
6

Die vor allem Ansätze sind korrekt und können funktionieren. Ich habe eine funktionierende Demo gemäß der obigen Anleitung erstellt und auf 2.x bis 5.x getestet

Sie können von Github klonen

Das Wichtigste zum Herumspielen ist die Hauptaktivität

toolbar = (Toolbar) findViewById(R.id.toolbar);
res = this.getResources();

this.setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    ScrimInsetsFrameLayout scrimInsetsFrameLayout = (ScrimInsetsFrameLayout)
            findViewById(R.id.linearLayout);
    scrimInsetsFrameLayout.setOnInsetsCallback(this);
} 

und der Rückruf

@Override
public void onInsetsChanged(Rect insets) {
    Toolbar toolbar = this.toolbar;
    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)
        toolbar.getLayoutParams();
    lp.topMargin = insets.top;
    int top = insets.top;
    insets.top += toolbar.getHeight();
    toolbar.setLayoutParams(lp);
    insets.top = top; // revert
}

Absolut das Theme für V21 macht die Magie

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- API 21 theme customizations can go here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/accent_material_light</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>

und das ScrimInsetsFrameLayout

Mit der neuen Design Support-Bibliothek wird dies jetzt einfacher

compile 'com.android.support:design:22.2.0'

Klon von @Chris Banes https://github.com/chrisbanes/cheesesquare

Vipin Sahu
quelle
4

Alle hier genannten Antworten sind zu alt und zu lang. Die beste und kurze Lösung, die mit der neuesten Navigationsansicht funktioniert, ist

@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
    super.onDrawerSlide(drawerView, slideOffset);

    try {
        //int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
            // Do something for lollipop and above versions

        Window window = getWindow();

        // clear FLAG_TRANSLUCENT_STATUS flag:
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

        // finally change the color to any color with transparency

         window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));}

    } catch (Exception e) {

        Crashlytics.logException(e);

    }
}

Dadurch wird die Farbe Ihrer Statusleiste beim Öffnen der Schublade in transparent geändert

Wenn Sie jetzt die Schublade schließen, müssen Sie die Farbe der Statusleiste wieder auf dunkel ändern. So können Sie dies tun.

        public void onDrawerClosed(View drawerView) {
        super.onDrawerClosed(drawerView);
        try {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
    // Do something for lollipop and above versions

    Window window = getWindow();

    // clear FLAG_TRANSLUCENT_STATUS flag:
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

    // finally change the color again to dark
    window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));}
    } catch (Exception e) {
    Crashlytics.logException(e);
                    }
                    }

und dann im Hauptlayout eine einzelne Zeile hinzufügen, dh

            android:fitsSystemWindows="true"

und Ihr Schubladenlayout wird so aussehen

            <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:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

und Ihre Navigationsansicht wird so aussehen

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/drawer"
        />

Ich habe es getestet und es funktioniert voll. Ich hoffe, es hilft jemandem. Dies ist vielleicht nicht der beste Ansatz, aber es funktioniert reibungslos und ist einfach zu implementieren. Markiere es, wenn es hilft. Glückliche Codierung :)

Harry Sharma
quelle
Wenn Sie eine benutzerdefinierte Ansicht in ActionBar verwenden, können Sie alternativ die Sichtbarkeit der benutzerdefinierten Ansicht in onDrawerSlide () auf INVISIBLE und in onDrawerClosed () auf VISIBLE setzen.
Mailand
3

Ich verwende die Design Support Library. Und nur durch die Verwendung eines benutzerdefinierten Themas habe ich beim Öffnen der Navigationsleiste eine transparente Statusleiste erreicht.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

<style name="NavigationStyle" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>

    <!-- To Make Navigation Drawer Fill Status Bar and become Transparent Too -->
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>

</style>

Fügen Sie schließlich ein Thema in die Manifest-Datei ein

<activity
  ........
  ........
 android:theme="@style/NavigationStyle"> 
</activity>

Vergessen Sie nicht, die Eigenschaft android:fitsSystemWindows="true"in "DrawerLayout" zu verwenden.

Katwal-Dipak
quelle
1
Wie verwende ich das für Geräte der API-Stufe 19?
AndroidGuy
2

Dies ist die einfachste und hat bei mir funktioniert:

In den Werten-21:

<resources>
    <style name="AppTheme" parent="AppTheme.Base">
        ...
        <item name="android:windowTranslucentStatus">true</item>
    </style>
    <dimen name="topMargin">25dp</dimen>
</resources>

In den Werten:

<resources>
    <dimen name="topMargin">0dp</dimen>
</resources>

Und stellen Sie Ihre Symbolleiste ein

android:layout_marginTop="@dimen/topMargin"
Nicolás López
quelle
Ich habe das auch gemacht und es hat wie ein Zauber auf Lollipop funktioniert. Aber ich habe 24dpfür den oberen Rand verwendet.
Rafa
Wenn Sie den Bildschirm auf Geräten mit Android 7.1 teilen, sehen Sie diese Lücke oben, wenn Ihre App der zweite Teil des Bildschirms ist.
Cícero Moura
1

Anstatt die ScrimInsetsFrameLayout... Ist es nicht einfacher, einfach eine Ansicht mit einer festen Höhe 24dpund einem Hintergrund von hinzuzufügen primaryColor?

Ich verstehe, dass dies das Hinzufügen einer Dummy-Ansicht in der Hierarchie beinhaltet, aber es scheint mir sauberer zu sein.

Ich habe es bereits versucht und es funktioniert gut.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_base_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- THIS IS THE VIEW I'M TALKING ABOUT... -->
        <View
            android:layout_width="match_parent"
            android:layout_height="24dp"
            android:background="?attr/colorPrimary" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/activity_base_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:elevation="2dp"
            android:theme="@style/ThemeOverlay.AppCompat.Dark" />

        <FrameLayout
            android:id="@+id/activity_base_content_frame_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <fragment
        android:id="@+id/activity_base_drawer_fragment"
        android:name="com.myapp.drawer.ui.DrawerFragment"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:elevation="4dp"
        tools:layout="@layout/fragment_drawer" />

</android.support.v4.widget.DrawerLayout>
mato
quelle
Wenn Sie den Bildschirm auf Geräten mit Android 7.1 teilen, sehen Sie diese Lücke oben, wenn Ihre App der zweite Teil des Bildschirms ist.
Cícero Moura
0

Versuchen Sie es damit:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout"
android:fitsSystemWindows="true">


<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--Main layout and ads-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <FrameLayout
            android:id="@+id/ll_main_hero"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

        </FrameLayout>

        <FrameLayout
            android:id="@+id/ll_ads"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <View
                android:layout_width="320dp"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:background="#ff00ff" />
        </FrameLayout>


    </LinearLayout>

    <!--Toolbar-->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/toolbar"
        android:elevation="4dp" />
</FrameLayout>


<!--left-->
<ListView
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:choiceMode="singleChoice"
    android:divider="@null"
    android:background="@mipmap/layer_image"
    android:id="@+id/left_drawer"></ListView>

<!--right-->
<FrameLayout
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:background="@mipmap/layer_image">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ken2"
        android:scaleType="centerCrop" />
</FrameLayout>

Stil:

<style name="ts_theme_overlay" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/red_A700</item>
    <item name="colorPrimaryDark">@color/red1</item>
    <item name="android:windowBackground">@color/blue_A400</item>
</style>

Hauptaktivität erweitert ActionBarActivity

toolBar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolBar);

Jetzt können Sie onCreateOptionsMenuwie gewohnt ActionBar mit ToolBar mögen.

Das ist mein Layout

  • OBEN: Linke Schublade - Rechte Schublade
    • MID: ToolBar (ActionBar)
    • UNTEN: ListFragment

Hoffe du verstehst! Viel Spaß!

Sohn Nguyen Thanh
quelle