Як використовувати DrawerLayout для відображення на панелі ActionBar / Toolbar та під панеллю стану?


394

Я бачив у дизайні нового матеріалу специфікація Side Nav, що ви можете відображати шухляду над панеллю дій та поза рядком стану. Як я можу це здійснити?


4
Навіть сьогодні не існує однозначної відповіді, яка б працювала із зворотною сумісністю. Такі питання справді дратують будь-якого програміста. Вже просуваємо API "N" та багато інших основних аспектів для вдосконалення в системі Android.
Валь Мартінес

Відповіді:


528

Нові функціональні можливості в рамках та вкладки підтримки дозволяють саме це. Є три "частини головоломки":

  1. Використання Панелі інструментів щоб ви могли вбудовувати панель дій у свою ієрархію перегляду.
  2. Створення DrawerLayout fitsSystemWindows таким чином, щоб він був за системними гратами.
  3. Вимкнення Theme.Materialзвичайного забарвлення рядка стану, щоб DrawerLayout міг намалювати там.

Я припускаю, що ви будете використовувати новий додаток.

По-перше, ваш макет повинен виглядати так:

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

Потім у вашій діяльності / фрагменті:

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

Тоді вам потрібно переконатися, що за рядком стану видно DrawerLayout. Ви робите це, змінюючи свою тему value-v21:

значення-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>

Примітка. Якщо <fragment android:name="fragments.NavigationDrawerFragment">замість A використовується а

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

    <!-- Your drawer content -->

</LinearLayout>

фактичного макета, бажаного ефекту буде досягнуто, якщо ви звернетесь fitsSystemWindows(boolean)до представлення, яке повертаєтесь із onCreateViewметоду.

@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
Так, DrawerLayoutпотреби в тому, щоб вони були розкладені за системними гратами. Потім вам потрібно встановити його у вікні ящика, щоб DrawerLayoutвін розкладав всередині віконних вкладишів.
Кріс Бейнс

11
Не можу це взагалі працювати. З наведеним вище кодом у новій демонстраційній програмі результат виглядає аналогічно описаному в @ScootrNova. Дивіться цей знімок
Michael Schmidt

6
Схоже, вам потрібно використовувати мінус layout_marginTopу корені макета вмісту вашого ящика. Інакше фон макета вмісту вашого ящика буде намальовано вгорі на панелі стану, а все інше буде натиснуто вниз. Це, однак, схоже на якесь грубе рішення, наскільки я знаю, що немає? Attr / statusBarSize або щось подібне, що постачається Android.
Шарль Мадере

26
Щоб отримати ефект, коли ящик видно через рядок стану, я закінчив налаштування android: fitsSystemWindows для помилки на DrawerLayout, android: fitsSystemWindows для істинного на моєму основному контентному макеті (макет, що містить Панель інструментів), і додав <ім'я елемента = "android: windowTranslucentStatus"> вірно </item> на мою тему - на Lollipop, тобто
Jakob

8
Ця відповідь неповна. Вам також потрібно загорнути свій навігаційний ящик всередині ScrimLayout. Дивіться stackoverflow.com/a/26926998/174149
Маркус Привіт

138

EDIT: Нова бібліотека підтримки дизайну підтримує це, і попередній метод більше не потрібен.

Цього можна досягти, використовуючи нове бібліотеку підтримки дизайну Android .

Ви можете побачити зразок програми Cheesesquare від Кріса Бейнса, який демонструє всі нові функції.


Попередній метод:

Оскільки жодного повного рішення не розміщено, ось як я досяг бажаного результату.

Спочатку включіть у свій проект ScrimInsetsFrameLayout .

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

Потім створіть стилізацію, щоб insetForegroundможна було встановити.

значення / attrs.xml

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

Оновіть xml-файл своєї діяльності та переконайтесь, що android:fitsSystemWindowsвстановлено значення true як на, DrawerLayoutтак і на 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>

Всередині методу onCreate вашої діяльності встановіть колір тла смуги стану на макеті ящика.

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

Нарешті оновіть тему програми, щоб DrawerLayout стояв за рядком стану.

значення-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>

Результат:


10
Це працювало найкраще для мене. Я витратив 2 дні на роботу над цією справою, і це одна. Це має бути позначено як відповідь. Дуже дякую.
kalehv

2
Я не використовую appcompat, і це не спрацювало. :( Чи є якийсь посібник, який працює з цим без додатків?
Джаред Руммлер

3
Це найдосконаліша відповідь. Я реалізував і протестував його на різних пристроях Android від 4.X до 5.X і можу підтвердити, що він працює чудово. Дуже дякую.
Арітра Рой

2
Як я вже сказав, це прекрасно працює, але у мене є невелика проблема. Діяльність з навігаційним ящиком має прозорий рядок стану, але всі інші дії втратили колір "основний знак" з рядка стану. Як повернути це?
Арітра Рой

5
Минуло три дні, щоб визнати, що в даний час немає іншого способу, як використовувати цей додатковий макет, обгорнутий навколо фрагмента ящика. Інакше рядок стану буде сірим (колір тла першої дитини), або ящик відображатиметься нижче рядка стану.
Денис Лох

96

З випуском новітньої бібліотеки підтримки Android (rev 22.2.0) у нас вийшла бібліотека підтримки підтримки дизайну, і як частина цього нового перегляду під назвою NavigationView . Тож замість того, щоб робити все самостійно разом із ScrimInsetsFrameLayoutусіма іншими речами, ми просто використовуємо цей погляд, і все робиться за нас.

Приклад

Крок 1

Додайте файл Design Support Libraryу свій build.gradleфайл

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

Крок 2

Додайте NavigationViewдо свого 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>

Крок 3

Створіть новий ресурс меню /res/menuта додайте елементи та піктограми, які ви хочете відобразити:

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

Крок 4

Запустіть NavigationView та обробляйте події клацання:

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

Крок 5

Не забудьте встановити android:windowDrawsSystemBarBackgroundsі android:statusBarColorв values-v21іншому випадку ваш ящик won`t буде відображатися «під» 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>

Необов’язковий крок

Додайте заголовок до NavigationView. Для цього просто створіть новий макет і додайте app:headerLayout="@layout/my_header_layout"до NavigationView.

Результат

зображення із поданням навігації

Примітки

  • Виділено кольором використовує колір , визначений з допомогою colorPrimaryатрибута
  • У Списку Предмети використовувати колір , визначений з допомогою textColorPrimaryатрибута
  • У Icons використовувати колір , визначений з допомогою textColorSecondaryатрибута

Ви також можете перевірити приклад програми на Кріса Бейнс , який висуває на перший план NavigationView поряд з іншими новими видами , які є частиною бібліотеки підтримки проектування (наприклад , в FloatingActionButton , TextInputLayout , закусочна , TabLayout і т.д.)


1
дякую @reVerse !!. > Якщо ви хочете оновити кожен елемент і значок у списку з файлів стилів, це можна зробити, використовуючи:<item name="itemTextColor">@color/YOUR_COLOR</item> <item name="itemIconTint">@color/YOUR_COLOR</item>
Juan Saravia

Як ви змінюєте колір тла вибраного елемента?
Joop

2
Цей підхід все ще виробляє NavigationView, який стоїть за ActionBar.
соутертон

1
@southerton, звичайно, вам доведеться використовувати Toolbar- немає способу зробити це зActionBar
reVerse

1
@ reegan29 Просто дзвоніть mDrawerLayout.openDrawer(GravityCompat.START);куди завгодно. Якщо ви користуєтеся ActionBarDrawerToggleцим, це слід зробити автоматично, як тільки ви натиснете на піктограму омбре.
reVerse

6

Зробити так, щоб у стилях value-v21 або темі xml потрібно використовувати цей атрибут:

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

Це робить магію!


3
Завдяки цьому моя панель дій також з’являється і за панеллю стану.
Міхель

Але це ефект, якого ми намагаємося досягти? Подивіться на додаток Gmail 5.0? Він показує бічну смужку позаду рядка стану.
Nicolas Jafelle

Це не те, що я хотів сказати. Навіть якщо ящик навігації знаходиться за панеллю стану з цим рядком коду, так само, як і панель інструментів / панель дій.
Міхель

2
Плакат і відповідач - це співробітник Google, який розробив AppCompat, тому я майже впевнений, що він знав, що робить, коли пише вміст.
afollestad

@Mixx, Ви можете встановити android: fitsSystemWindows = "true" для вашого звичайного перегляду вмісту (якщо, наприклад, прийнятий макет відповідей). Це може працювати навіть для Android 4.4. Але тут є невелика різниця: в Android 5.0 рівень прозорості на панелі стану дещо вищий (вище значення альфа), ніж у GMail, що робить смугу стану ще темнішою.
Qianqian

6

Наведені вище підходи є правильними та можуть працювати. Я створив робочу демонстрацію, дотримуючись вищезазначеного керівництва і протестувавши на 2.x до 5.x

Ви можете клонуватися з Github

Важлива річ, яку потрібно грати, - це Основна діяльність

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

і передзвоніть

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

Абсолютно Тема для V21 робить магію

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

і макет ScrimInsetsFrameLayout

Тепер це стає легше завдяки новій бібліотеці підтримки підтримки дизайну

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

клон від @Chris Banes https://github.com/chrisbanes/cheesesquare


4

Усі відповіді, згадані тут, занадто давні та тривалі. Найкраще і коротке рішення, яке працює з останніми Navigationview, - це

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

    }
}

це змінить колір рядка стану на прозорий, коли ви відкриєте ящик

Тепер, коли ви закриєте шухляду, вам потрібно знову змінити колір рядка стану на темний. Отже, ви можете зробити це таким чином.

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

а потім в основний макет додайте один рядок, тобто

            android:fitsSystemWindows="true"

і ваш макет ящика буде виглядати так

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

і ваш вигляд навігації буде виглядати таким чином

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

Я перевірив це і його повністю працює. Надіюсь, він комусь допомагає. Це може бути не найкращим підходом, але він працює гладко і простий у виконанні. Позначте це, якщо це допоможе. Швидке кодування :)


Крім того, якщо ви використовуєте спеціальний вигляд у ActionBar, ви можете встановити видимість користувальницького перегляду на INVISIBLE в onDrawerSlide () та на VISIBLE в onDrawerClosed ().
Мілан

3

Я використовую бібліотеку підтримки дизайну. І лише використовуючи власну тему, я досяг прозорого рядка стану, коли відкрився навігаційний ящик.

введіть тут опис зображення

введіть тут опис зображення

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

Нарешті додайте тему у файл Manifest

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

Не забудьте скористатися властивістю android:fitsSystemWindows="true"в "DrawerLayout"


1
як це використовувати для пристроїв api рівня 19?
AndroidGuy

2

Це найпростіше, і це працювало для мене:

У значеннях-21:

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

У значеннях:

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

І встановіть на панель інструментів

android:layout_marginTop="@dimen/topMargin"

Я теж робив це, і це спрацьовувало, як чарівність, на Lollipop. Але я використовував 24dpверхню маржу.
Рафа

Якщо розділити екран на пристроях під керуванням Android 7.1, ви побачите цю прогалину вгорі, якщо у вас додаток є другою частиною екрана.
Cícero Moura

1

Замість використання ScrimInsetsFrameLayout... Чи не простіше просто додати вид із фіксованою висотою 24dpта фономprimaryColor ?

Я розумію, що це передбачає додавання фіктивного погляду в ієрархію, але мені це здається більш чистим.

Я вже спробував це, і він працює добре.

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

Якщо розділити екран на пристроях під керуванням Android 7.1, ви побачите цю прогалину вгорі, якщо у вас додаток є другою частиною екрана.
Cícero Moura

0

Спробуйте з цим:

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

стиль:

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

Основна діяльність розширює ActionBarActivity

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

Тепер ви можете onCreateOptionsMenuподобатися як звичайний ActionBar з ToolBar.

Це моя макет

  • ВЕРХ: Лівий ящик - правий ящик
    • MID: Панель інструментів (ActionBar)
    • BOTTOM: СписокFragment

Сподіваюся, ви зрозуміли! Весело!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.