Bagaimana cara menggunakan DrawerLayout untuk menampilkan ActionBar / Toolbar dan di bawah bilah status?


394

Saya telah melihat dalam spesifikasi desain material Side Nav baru bahwa Anda dapat menampilkan laci di atas panel tindakan dan di belakang panel status. Bagaimana saya bisa menerapkan ini?


4
Bahkan hari ini tidak ada jawaban yang jelas yang bekerja dengan kompatibilitas ke belakang. Masalah-masalah semacam ini benar-benar menjengkelkan programmer mana pun. Sudah mempromosikan API "N" dan banyak aspek dasar untuk diperbaiki di sistem Android.
Val Martinez

Jawaban:


528

Fungsionalitas baru dalam kerangka kerja dan dukungan lib memungkinkan ini terjadi. Ada tiga 'kepingan puzzle':

  1. Menggunakan Bilah Alat sehingga Anda bisa menyematkan bilah tindakan ke hierarki tampilan.
  2. Membuat DrawerLayout fitsSystemWindows sehingga diletakkan di belakang bilah sistem.
  3. Menonaktifkan Theme.Materialpewarnaan bilah status normal sehingga DrawerLayout dapat menggambar di sana.

Saya akan berasumsi bahwa Anda akan menggunakan appcompat baru.

Pertama, tata letak Anda akan terlihat seperti ini:

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

Kemudian di Aktivitas / Fragmen Anda:

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

Maka Anda perlu memastikan bahwa DrawerLayout terlihat di belakang bilah status. Anda melakukannya dengan mengubah nilai-v21 tema Anda:

values-v21 / themes.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>

Catatan: Jika a <fragment android:name="fragments.NavigationDrawerFragment">digunakan sebagai ganti

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

    <!-- Your drawer content -->

</LinearLayout>

tata letak yang sebenarnya, efek yang diinginkan akan tercapai jika Anda memanggil fitsSystemWindows(boolean)tampilan yang Anda kembali dari onCreateViewmetode.

@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;
}

3
Ya, DrawerLayoutperlu diletakkan di belakang panel sistem. Anda kemudian perlu mengaturnya pada tampilan laci sehingga DrawerLayoutmeletakkannya di dalam insets jendela.
Chris Banes

11
Tidak bisa ini bekerja sama sekali. Dengan kode di atas dalam aplikasi demo baru, hasilnya terlihat mirip dengan yang dijelaskan oleh @ScootrNova. Lihat Screenshot ini: imgur.com/QLk3syt
Michael Schmidt

6
Sepertinya Anda benar-benar perlu menggunakan negatif layout_marginTopdi root tata letak konten laci Anda. Jika tidak, latar belakang tata letak konten laci Anda akan digambar di atas bilah status, dan yang lainnya akan didorong ke bawah. Namun ini sepertinya solusi yang agak kotor, sejauh yang saya tahu tidak ada? Attr / statusBarSize atau yang seperti itu disediakan oleh Android.
Charles Madere

26
Untuk mendapatkan efek di mana laci terlihat melalui bilah status, saya akhirnya menetapkan android: fitsSystemWindows menjadi false di DrawerLayout, android: fitsSystemWindows untuk true pada tata letak konten utama saya (tata letak yang berisi Toolbar), dan menambahkan <nama item = "android: windowTranslucentStatus"> true </item> dengan tema saya - di Lollipop
Jakob

8
Jawaban ini tidak lengkap. Anda juga perlu membungkus laci navigasi Anda di dalam ScrimLayout. Lihat stackoverflow.com/a/26926998/174149
Markus Hi

138

EDIT: Perpustakaan Dukungan Desain baru mendukung ini dan metode sebelumnya tidak lagi diperlukan.

Ini sekarang dapat dicapai menggunakan Perpustakaan Dukungan Desain Android baru .

Anda dapat melihat aplikasi sampel Cheesesquare oleh Chris Banes yang melakukan demo semua fitur baru.


Metode sebelumnya:

Karena tidak ada solusi lengkap yang diposting, berikut adalah cara saya mencapai hasil yang diinginkan.

Pertama, sertakan ScrimInsetsFrameLayout dalam proyek Anda.

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

Kemudian buat yang gaya agar insetForegroundbisa diatur.

nilai / attrs.xml

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

Memperbarui file xml aktivitas Anda dan pastikan android:fitsSystemWindowsdiatur ke benar pada kedua DrawerLayoutserta ScrimInsetsFrameLayout.

tata letak / 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>

Di dalam metode onCreate aktivitas Anda, atur warna latar belakang bilah status pada tata letak laci.

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

Terakhir perbarui tema aplikasi Anda sehingga DrawerLayoutada di belakang bilah status.

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>

Hasil:


10
Ini yang terbaik bagi saya. Saya menghabiskan 2 hari untuk mendapatkan pekerjaan ini dan ini adalah satu. Ini harus ditandai sebagai Jawaban. Terima kasih banyak.
kalehv

2
Saya tidak menggunakan appcompat dan ini tidak berhasil. :( Apakah ada panduan yang membuat ini berfungsi tanpa appcompat?
Jared Rummler

3
Ini jawaban yang paling sempurna. Saya telah menerapkan dan mengujinya di berbagai perangkat Android dari 4.X hingga 5.X dan dapat mengonfirmasi bahwa itu berfungsi dengan baik. Terima kasih banyak.
Aritra Roy

2
Seperti yang saya katakan, ini bekerja dengan sempurna, tetapi saya punya sedikit masalah. Aktivitas dengan Drawer Navigasi memiliki bilah status transparan, tetapi semua aktivitas lain telah kehilangan warna "primer" dari bilah status. Bagaimana cara mendapatkannya kembali?
Aritra Roy

5
Butuh waktu tiga hari untuk menerima bahwa saat ini tidak ada cara lain selain menggunakan tata letak tambahan ini yang melilit bagian laci. Kalau tidak, bilah status akan berwarna abu-abu (warna latar belakang anak pertama) atau laci akan ditampilkan di bawah bilah status.
Denis Loh

96

Dengan rilis Perpustakaan Dukungan Android terbaru (rev 22.2.0), kami memiliki Perpustakaan Dukungan Desain dan sebagai bagian dari ini tampilan baru bernama NavigationView . Jadi alih-alih melakukan semuanya sendiri dengan ScrimInsetsFrameLayoutdan semua hal lain, kita cukup menggunakan pandangan ini dan semuanya dilakukan untuk kita.

Contoh

Langkah 1

Tambahkan Design Support Libraryke build.gradlefile Anda

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

Langkah 2

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

Langkah 3

Buat sumber daya menu baru /res/menudan tambahkan item dan ikon yang ingin Anda tampilkan:

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

Langkah 4

Init the NavigationView dan tangani acara klik:

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

Langkah 5

Pastikan untuk set android:windowDrawsSystemBarBackgroundsdan android:statusBarColordi values-v21lain Laci Anda memenangkan `t ditampilkan "bawah" 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>

Langkah Opsional

Tambahkan Header ke NavigationView. Untuk ini, cukup buat layout baru dan tambahkan app:headerLayout="@layout/my_header_layout"ke NavigationView.

Hasil

gambar yang menunjukkan tampilan navigasi

Catatan

  • The warna disorot menggunakan warna didefinisikan melalui colorPrimaryatribut
  • The Daftar Produk menggunakan warna didefinisikan melalui textColorPrimaryatribut
  • The Ikon menggunakan warna didefinisikan melalui textColorSecondaryatribut

Anda juga dapat memeriksa contoh aplikasi oleh Chris Banes yang menyoroti NavigationView bersama dengan pandangan baru lainnya yang merupakan bagian dari Perpustakaan Dukungan Desain (seperti FloatingActionButton , TextInputLayout , Snackbar , TabLayout dll.)


1
terima kasih @reVerse !!. > Jika Anda ingin memperbarui setiap item dan ikon dalam daftar dari file style, Anda dapat melakukannya menggunakan:<item name="itemTextColor">@color/YOUR_COLOR</item> <item name="itemIconTint">@color/YOUR_COLOR</item>
Juan Saravia

Bagaimana Anda mengubah warna latar belakang item yang dipilih?
Joop

2
Pendekatan ini masih menghasilkan NavigationView yang ada di belakang ActionBar.
southerton

1
@southerton tentu saja, Anda harus menggunakan Toolbar- tidak ada cara untuk melakukan ini denganActionBar
reVerse

1
@ reegan29 Cukup telepon ke mDrawerLayout.openDrawer(GravityCompat.START);mana pun Anda mau. Jika Anda menggunakan ActionBarDrawerToggleini harus dilakukan secara otomatis segera setelah Anda mengklik ikon hamburger.
Kembalikan

6

Buat itu berfungsi, dalam nilai-v21 gaya atau tema xml perlu menggunakan atribut ini:

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

Itu membuat keajaiban!


3
Ini membuat actionbar saya juga muncul di belakang bilah status.
Michiel

Tapi itulah efek yang kami coba capai, lihat aplikasi Gmail 5.0? Ini menunjukkan Bilah Sisi di belakang bilah status.
Nicolas Jafelle

Bukan itu yang ingin saya katakan. Meskipun laci navigasi berada di belakang bilah status dengan baris kode ini, begitu juga bilah alat / bilah tindakan.
Michiel

2
Poster dan penjawab adalah karyawan Google yang merancang AppCompat, jadi saya cukup yakin dia tahu apa yang dia lakukan ketika dia menulis konten.
afollestad

@Mixx, Anda dapat mengatur android: fitsSystemWindows = "true" untuk tampilan konten normal Anda (jika menggunakan tata letak jawaban yang diterima misalnya). Itu bisa bekerja, bahkan untuk Android 4.4. Tetapi ada sedikit perbedaan di sini: Di ​​Android 5.0 tingkat transparansi pada bilah status agak lebih tinggi (nilai alfa lebih tinggi) daripada di GMail, membuat bilah status lebih gelap.
Qianqian

6

Semua pendekatan di atas benar dan mungkin berhasil. Saya telah membuat demo yang berfungsi mengikuti panduan di atas dan diuji pada 2.x hingga 5.x

Anda dapat mengkloning dari Github

Yang penting untuk dimainkan adalah di Main Activity

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

dan telepon kembali

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

Absolutely the Theme untuk V21 melakukan keajaiban

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

dan ScrimInsetsFrameLayout

Sekarang ini menjadi lebih mudah dengan perpustakaan Dukungan Desain baru

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

klon dari @Chris Banes https://github.com/chrisbanes/cheesesquare


4

Semua jawaban yang disebutkan di sini terlalu lama dan panjang. Solusi terbaik dan pendek yang bekerja dengan Navigationview terbaru adalah

@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);

    }
}

ini akan mengubah warna bilah status Anda menjadi transparan saat Anda membuka laci

Sekarang ketika Anda menutup laci Anda perlu mengubah warna bilah status lagi menjadi gelap. Jadi Anda bisa melakukannya dengan cara ini.

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

dan kemudian di tata letak utama tambahkan satu baris yaitu

            android:fitsSystemWindows="true"

dan tata letak laci Anda akan terlihat seperti

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

dan tampilan navigasi Anda akan terlihat seperti

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

Saya telah mengujinya dan berfungsi sepenuhnya. Semoga bisa membantu seseorang. Ini mungkin bukan pendekatan terbaik tetapi bekerja dengan lancar dan mudah diterapkan. Tandai jika itu membantu. Selamat coding :)


Atau, jika Anda menggunakan tampilan kustom di ActionBar, Anda bisa mengatur visibilitas tampilan kustom menjadi INVISIBLE di onDrawerSlide () dan untuk TERLIHAT di onDrawerClosed ().
Milan

3

Saya Menggunakan Perpustakaan Dukungan Desain. Dan hanya dengan menggunakan tema khusus, saya mendapatkan Status Bar transparan ketika Dibuka Navigasi Drawer.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

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

Akhirnya tambahkan tema di File Manifest

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

Jangan lupa untuk menggunakan properti, android:fitsSystemWindows="true"di "DrawerLayout"


1
bagaimana cara menggunakan ini untuk perangkat api level 19?
AndroidGuy

2

Ini yang paling sederhana, dan itu berhasil untuk saya:

Dalam nilai-21:

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

Dalam nilai:

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

Dan atur ke toolbar Anda

android:layout_marginTop="@dimen/topMargin"

Saya juga melakukan ini, dan itu berfungsi seperti pesona pada Lollipop. Tapi saya menggunakan 24dpmargin atas.
Rafa

Ketika Anda membagi layar pada perangkat dengan Android 7.1 Anda dapat melihat celah ini di atas jika aplikasi Anda adalah bagian kedua dari layar.
Cícero Moura

1

Alih-alih menggunakan ScrimInsetsFrameLayout... Bukankah lebih mudah untuk hanya menambahkan tampilan dengan ketinggian tetap 24dpdan latar belakang primaryColor?

Saya mengerti bahwa ini melibatkan menambahkan pandangan boneka dalam hierarki, tetapi tampaknya lebih bersih bagi saya.

Saya sudah mencobanya dan berhasil.

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

Ketika Anda membagi layar pada perangkat dengan Android 7.1 Anda dapat melihat celah ini di atas jika aplikasi Anda adalah bagian kedua dari layar.
Cícero Moura

0

Coba dengan ini:

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

gaya:

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

Kegiatan Utama memperluas ActionBarActivity

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

Sekarang Anda bisa onCreateOptionsMenuseperti ActionBar biasa dengan ToolBar.

Ini Layout saya

  • TOP: Left Drawer - Drawer Kanan
    • MID: ToolBar (ActionBar)
    • BOTTOM: ListFragment

Semoga Anda mengerti! Bersenang-senang!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.