Frage Navigationsleiste halbtransparent über Statusleiste funktioniert nicht


Ich arbeite an einem Android-Projekt und implementiere die Navigationsschublade. Ich lese das Neue durch Material Design Spec und das Material Design Checkliste.
Die Spezifikation besagt, dass das Ausklappfenster über alles andere, einschließlich der Statusleiste, schweben und über die Statusleiste halbtransparent sein sollte.

Meine Navigationsleiste befindet sich über der Statusleiste, hat jedoch keine Transparenz. Ich habe den Code von hier gefolgt DAMIT posten Sie wie im Google Developers Blog-Spot vorgeschlagen, Link oben Wie verwende ich DrawerLayout zur Anzeige über die ActionBar / Toolbar und unter der Statusleiste?.

Unten ist mein XML-Layout

<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">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <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="@color/appPrimaryColour" />
    </LinearLayout>
    <LinearLayout android:id="@+id/linearLayout"
        android:layout_width="304dp"
        android:layout_height="match_parent"
        android:layout_gravity="left|start"
        android:fitsSystemWindows="true"
        android:background="#ffffff">
        <ListView android:id="@+id/left_drawer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:choiceMode="singleChoice"></ListView>
    </LinearLayout>
</android.support.v4.widget.DrawerLayout>

Im Folgenden finden Sie das Thema meiner Apps

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/appPrimaryColour</item>
        <item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
        <item name="colorAccent">@color/appPrimaryColour</item>
        <item name="windowActionBar">false</item>
        <item name="windowActionModeOverlay">true</item>

    </style>

Unten ist mein apps v21-Thema

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/appPrimaryColour</item>
    <item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
    <item name="colorAccent">@color/appPrimaryColour</item>
    <item name="windowActionBar">false</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

Unten ist meine onCreate-Methode

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

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

    mDrawerLayout = (DrawerLayout)findViewById(R.id.my_drawer_layout);
    mDrawerList = (ListView)findViewById(R.id.left_drawer);

    mDrawerLayout.setStatusBarBackgroundColor(
        getResources().getColor(R.color.appPrimaryColourDark));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        LinearLayout linearLayout = 
            (LinearLayout)findViewById(R.id.linearLayout);
        linearLayout.setElevation(30);
    }

Unten ist ein Bildschirmfoto von meiner Navigationsschublade, die das Oberteil zeigt, ist nicht halbtransparent

Screenshot showing non transparent over the status bar


76
2017-11-04 21:23


Ursprung


Antworten:


Ihr Statusleistenhintergrund ist weiß, der Hintergrund Ihrer Schublade LinearLayout. Warum? Sie sind Einstellungen fitsSystemWindows="true" für dein DrawerLayout und das LinearLayout im Inneren. Dies verursacht deine LinearLayout erweitern hinter die Statusleiste (die transparent ist). So wird der Hintergrund für die Schublade Teil der Statusleiste weiß.

enter image description here
Wenn Sie nicht möchten, dass sich Ihre Schublade hinter die Statusleiste erstreckt (Sie möchten einen halbtransparenten Hintergrund für die gesamte Statusleiste haben), können Sie zwei Dinge tun:

1) Sie können einfach jeden Hintergrundwert von Ihrem entfernen LinearLayout und färbe den Hintergrund deines Inhalts darin ein. Oder

2) Sie können entfernen fitsSystemWindows="true" von deiner LinearLayout. Ich denke, das ist ein logischer und sauberer Ansatz. Sie vermeiden außerdem, dass in der Statusleiste ein Schatten geworfen wird, in dem sich die Navigationsleiste nicht erstreckt.

enter image description here
Wenn Sie möchten, dass sich Ihre Schublade hinter der Statusleiste erstreckt und ein halbtransparentes, in der Statusleiste angeordnetes Overlay aufweist, können Sie a verwenden ScrimInsetFrameLayout als Container für Ihren Schubladeninhalt (ListView) und setzen Sie den Hintergrund der Statusleiste mit app:insetForeground="#4000". Natürlich können Sie ändern #4000 zu allem, was du willst. Vergiss nicht, zu behalten fitsSystemWindows="true" Hier!

Oder wenn Sie Ihren Inhalt nicht überlagern und nur eine Volltonfarbe anzeigen möchten, können Sie einfach den Hintergrund Ihres LinearLayout zu allem, was du willst. Vergessen Sie nicht, den Hintergrund Ihrer Inhalte separat festzulegen!

BEARBEITEN: Sie müssen sich damit nicht mehr befassen. Bitte sehen Design-Support-Bibliothek für eine einfachere Navigation Schublade / Ansicht Implementierung.


95
2017-11-14 14:27



Alles, was Sie tun müssen, ist eine halbtransparente Farbe für die Statusleiste zu verwenden. Fügen Sie diese Zeilen zu Ihrem v21-Thema hinzu:

<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@color/desired_color</item>

Vergiss nicht, dass die color (Ressource) muss immer im Format von #AARRGGBB. Dies bedeutet, dass die Farbe auch den Alpha-Wert enthält.


29
2017-11-05 20:52



Warum nicht etwas ähnliches verwenden?

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

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

    <ListView
            android:id="@+id/left_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:choiceMode="singleChoice"
            android:divider="@android:color/transparent"
            android:dividerHeight="0dp"
            android:background="#80111111"/>
</android.support.v4.widget.DrawerLayout>

Der obige Code verwendet die Alpha-Ressource in der android:background Transparenz in der Aktionsleiste zeigen zu können.

Es gibt andere Möglichkeiten, dies über Code zu tun, wie andere Antworten zeigen. Meine Antwort oben, tut das notwendige in der XML-Layout-Datei, die meiner Meinung nach leicht bearbeitet werden kann.


15
2017-11-11 12:27



Sie müssen das Layout Ihres Navigationsschubladens in ein ScrimLayout.

EIN ScrimLayout im Grunde zieht ein halbtransparentes Rechteck über das Layout Ihrer Navigationsleiste. Um die Größe des Insets abzurufen, überschreiben Sie einfach fitSystemWindows in deinem ScrimLayout.

@Override
protected boolean fitSystemWindows(Rect insets) {
    mInsets = new Rect(insets);
    return true;
}

Später überschreiben onDraw ein halbtransparentes Rechteck zeichnen.

Ein Beispiel Implementierung finden Sie in der Google IO App-Quelle. Hier Sie können sehen, wie es im Layout-XML verwendet wird.


8
2017-11-14 09:43



Wenn Sie möchten, Navigationsbereich ist über die Statusleiste und halbtransparent über die Statusleiste. Google I / O Android App Quelle bietet eine gute Lösung (APK im Play Store werden nicht auf die letzte Version aktualisiert

Zuerst brauchst du einen ScrimInsetFrameLayout

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

Dann ändern Sie in Ihrem XML-Layout diesen Teil

<LinearLayout android:id="@+id/linearLayout"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true"
    android:background="#ffffff">
    <ListView android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"></ListView>
</LinearLayout>

Ändern Sie LinearLayout wie folgt in Ihr ScrimInsetFrameLayout

<com.boardy.util.ScrimInsetFrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearLayout"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:fitsSystemWindows="true"
    app:insetForeground="#4000">
    <ListView android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"></ListView>
</com.boardy.util.ScrimInsetFrameLayout>

6
2017-11-15 08:49



Ich hatte eine ähnliche Funktion in meinem Projekt zu implementieren. Und um meine Schublade transparent zu machen, benutze ich einfach die Transparenz für Hex-Farben. Mit 6 Hexadezimalziffern haben Sie 2 Hexadezimalziffern für jeden Wert von Rot, Grün und Blau. aber wenn Sie zwei zusätzliche Ziffern (8 Hex-Ziffern), so haben Sie ARGB (zwei Ziffern für Alpha-Wert) (Schau hier).

Hier sind die Hex-Opazitätswerte: für die 2 zusätzlichen Ziffern

100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — A6
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00

Zum Beispiel: Wenn Sie die Hexadezimalfarbe (# 111111) haben, setzen Sie einfach einen der Opazitätswerte, um Transparenz zu erhalten. so: (# 11111100)

Meine Schublade deckt nicht die Aktionsleiste ab (wie Ihre), aber die Transparenz kann auch in diesen Fällen angewendet werden. Hier ist mein Code:

     <ListView
          android:id="@+id/left_drawer"
          android:layout_width="240dp"
          android:layout_height="match_parent"
          android:layout_gravity="start"
          android:background="#11111100"
          android:choiceMode="singleChoice"
          android:divider="@android:color/transparent"
          android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

Und hier ist ein anderer Artikel Das kann Ihnen helfen, die Alpha-Codes in Hex-Farben zu verstehen.


4
2017-11-14 13:24



Alle hier genannten Antworten sind zu alt und zu lang. Die beste und kürzeste Lösung, die mit der neuesten Navigationssoftware funktioniert

@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 der Statusleiste beim Öffnen der Schublade transparent angezeigt

Jetzt, wenn Sie die Schublade schließen, müssen Sie die Farbe der Statusleiste wieder auf dunkel ändern. So können Sie es auf diese Weise tun.

@Override
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, d.h.

            android:fitsSystemWindows="true"

und Ihr Schubladenlayout wird 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 deine Navigationsansicht wird wie folgt 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 und ganz. Ich hoffe, es hilft jemandem. Dies ist vielleicht nicht der beste Ansatz, aber es funktioniert reibungslos und ist einfach zu implementieren. Markieren Sie es, wenn es hilft.Happy code :)


2
2018-02-12 12:28