Как использовать DrawerLayout для отображения поверх панели инструментов / панели инструментов и под строкой состояния?

394

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

Крис Бейнс
источник
4
Даже сегодня нет четкого ответа, который работает с обратной совместимостью. Подобные проблемы действительно раздражают любого программиста. Уже продвигаю «N» API и многие другие основные аспекты для улучшения в системе Android.
Вэл Мартинес

Ответы:

528

Новая функциональность в фреймворке и поддержка библиотек позволяют именно это. Есть три «кусочка головоломки»:

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

Я предполагаю, что вы будете использовать новый appcompat.

Во-первых, ваш макет должен выглядеть так:

<!-- 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 виден за строкой состояния. Вы делаете это, изменяя тему values-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">вместо

<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. Смотрите этот снимок
Майкл Шмидт
6
Похоже, вам действительно нужно использовать минус layout_marginTopв корне макета содержимого вашего ящика. В противном случае фон макета содержимого вашего ящика будет отображаться в верхней части строки состояния, а все остальное будет перемещено вниз. Это, однако, кажется довольно грубым решением, насколько я знаю, что нет? Attr / statusBarSize или чего-то подобного, поставляемого Android.
Чарльз Мадер
26
Чтобы получить эффект, когда ящик виден через строку состояния, я в конечном итоге установил для android: fitsSystemWindows значение false в DrawerLayout, для android: fitsSystemWindows в значение true в моем основном макете содержимого (макет, содержащий панель инструментов) и добавил <имя элемента = "android: windowTranslucentStatus"> true </ item> к моей теме - на Lollipop, то есть
Jakob
8
Этот ответ неполон. Вы также должны обернуть свой навигационный ящик в ScrimLayout. См. Stackoverflow.com/a/26926998/174149
Маркус Привет,
138

РЕДАКТИРОВАТЬ: Новая библиотека поддержки дизайна поддерживает это, и предыдущий метод больше не требуется.

Теперь это можно сделать с помощью новой библиотеки поддержки дизайна Android .

Вы можете увидеть пример приложения Cheesesquare от Chris Banes, который демонстрирует все новые функции.


Предыдущий метод:

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

Сначала включите 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.

макет / 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>

Результат:

Suyash
источник
10
Это сработало лучше для меня. Я потратил 2 дня, чтобы заставить эту вещь работать, и это одна. Это должно быть отмечено как Ответ. Огромное спасибо.
kalehv
2
Я не использую appcompat, и это не сработало. :( Есть ли какой-нибудь путеводитель, который заставит это работать без appcompat?
Джаред Раммлер
3
Это самый совершенный ответ. Я внедрил и протестировал его на различных устройствах Android от 4.X до 5.X и могу подтвердить, что он работает отлично. Большое спасибо.
Аритра Рой
2
Как я уже сказал, это работает отлично, но у меня есть небольшая проблема. Операция с Навигатором навигации имеет прозрачную строку состояния, но все остальные действия потеряли цвет «primaryDark» из строки состояния. Как вернуть это?
Аритра Рой
5
Мне потребовалось три дня, чтобы признать, что в настоящее время нет другого пути, кроме как использовать этот дополнительный макет, обернутый вокруг фрагмента ящика. В противном случае строка состояния будет либо серой (цвет фона первого ребенка), либо ящик будет отображаться под строкой состояния.
Денис Лох
96

С выпуском последней библиотеки поддержки Android (версия 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противном случае ваш ящик не будет отображаться «под» 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>
Хуан Саравиа
Как изменить цвет фона выбранного элемента?
Joop
2
Этот подход все еще создает NavigationView, который находится за ActionBar.
Саутертон
1
@southerton, конечно, вы должны использовать Toolbar- нет никакого способа сделать это сActionBar
reVerse
1
@ reegan29 Просто звоните, mDrawerLayout.openDrawer(GravityCompat.START);куда хотите. Если вы используете это, ActionBarDrawerToggleэто должно быть сделано автоматически, как только вы нажмете на значок гамбургера.
Пересмотрите
6

Чтобы это работало, в values-v21 styles или theme xml необходимо использовать этот атрибут:

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

Это делает волшебство!

Николя Жафель
источник
3
Это заставляет мою панель действий появляться и за строкой состояния.
Michiel
Но это тот эффект, которого мы пытаемся достичь, посмотрите на приложение Gmail 5.0? Он показывает боковую панель за строкой состояния.
Николя Жафель
Это не то, что я хотел сказать. Несмотря на то, что панель навигации находится за строкой состояния с этой строкой кода, как и панель инструментов / панель действий.
Michiel
2
Постер и ответчик - сотрудник Google, который разработал AppCompat, поэтому я почти уверен, что он знал, что делал, когда писал контент.
Афоллестад
@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 File

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

Не забудьте использовать свойство, android:fitsSystemWindows="true"в «DrawerLayout»

katwal-Дипак
источник
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, вы можете увидеть этот пробел вверху, если ваше приложение является второй частью экрана.
Сисеро Моура
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, вы можете увидеть этот пробел вверху, если ваше приложение является второй частью экрана.
Сисеро Моура
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)
    • Дно: ListFragment

Надеюсь, вы понимаете! Веселитесь!

Сын Нгуен Тхань
источник