rapido opciones herramientas funciones definicion cinta barra acceso android navigation-drawer appcompat android-appcompat

android - opciones - ¿Cómo uso DrawerLayout para mostrar sobre la barra de acciones/barra de herramientas y debajo de la barra de estado?



cinta de opciones (10)

EDITAR: La nueva Biblioteca de soporte de diseño lo admite y ya no se requiere el método anterior.

Esto ahora se puede lograr utilizando la nueva Biblioteca de soporte de diseño de Android .

Puede ver la aplicación de ejemplo Cheesesquare de Chris Banes que muestra todas las nuevas características.

Método anterior:

Como no hay una solución completa publicada, esta es la forma en que logré el resultado deseado.

Primero incluya un ScrimInsetsFrameLayout en su proyecto.

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

Luego, cree un estilo para que se pueda establecer insetForeground .

valores / attrs.xml

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

Actualice el archivo xml de su actividad y asegúrese de que android:fitsSystemWindows esté configurado como verdadero tanto en DrawerLayout como en 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>

Dentro del método onCreate de su actividad, configure el color de fondo de la barra de estado en el diseño del cajón.

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

Finalmente, actualice el tema de su aplicación para que DrawerLayout esté detrás de la barra de estado.

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>

Resultado:

He visto en la nueva especificación Side Nav de diseño de material que puede mostrar el cajón sobre la barra de acción y detrás de la barra de estado. ¿Cómo puedo implementar esto?


Con el lanzamiento de la última biblioteca de soporte de Android (rev 22.2.0) tenemos una biblioteca de soporte de diseño y, como parte de esto, una nueva vista llamada NavigationView . Entonces, en lugar de hacer todo por nuestra cuenta con ScrimInsetsFrameLayout y todas las demás cosas, simplemente usamos esta vista y todo se hace por nosotros.

Ejemplo

Paso 1

Agregue la Design Support Library a su archivo build.gradle

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

Paso 2

Agregue NavigationView a su 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>

Paso 3

Cree un nuevo recurso de menú en /res/menu y agregue los elementos e iconos que desea mostrar:

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

Paso 4

Inicie el NavigationView y maneje los eventos de clic:

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

Paso 5

Asegúrese de configurar android:windowDrawsSystemBarBackgrounds y android:statusBarColor en values-v21 contrario, su Drawer no se mostrará "debajo" de 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>

Paso opcional

Agregue un encabezado a NavigationView. Para esto, simplemente cree un nuevo diseño y agregue la app:headerLayout="@layout/my_header_layout" a NavigationView.

Resultado

Notas

  • El color resaltado utiliza el color definido a través del atributo colorPrimary
  • Los elementos de la lista usan el color definido a través del atributo textColorPrimary
  • Los iconos usan el color definido a través del atributo textColorSecondary

También puede consultar la aplicación de ejemplo de Chris Banes que resalta NavigationView junto con otras vistas nuevas que forman parte de la Biblioteca de soporte de diseño (como FloatingActionButton , TextInputLayout , Snackbar , TabLayout , etc.)


En lugar de usar ScrimInsetsFrameLayout ... ¿No es más fácil agregar una vista con una altura fija de 24dp y un fondo de primaryColor ?

Entiendo que esto implica agregar una vista ficticia en la jerarquía, pero me parece más limpia.

Ya lo probé y está funcionando bien.

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


Este es el más simple, y funcionó para mí:

En los valores-21:

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

En los valores:

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

Y configúralo en tu barra de herramientas

android:layout_marginTop="@dimen/topMargin"


Haz que funcione, en los valores-v21 estilos o tema xml necesita usar este atributo:

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

Eso hace la magia!


La nueva funcionalidad en el marco y las bibliotecas de soporte permiten exactamente esto. Hay tres ''piezas del rompecabezas'':

  1. Usando la Toolbar para que puedas insertar tu barra de acción en tu jerarquía de vistas.
  2. Hacer que DrawerLayout fitsSystemWindows DrawerLayout fitsSystemWindows para que se fitsSystemWindows detrás de las barras del sistema.
  3. Desactivar el Theme.Material de la barra de estado normal de Theme.Material para que DrawerLayout pueda dibujar allí.

Asumiré que usará la nueva aplicacióncompat.

Primero, su diseño debería verse así:

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

Luego en tu Actividad / Fragmento:

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

Luego debe asegurarse de que DrawerLayout esté visible detrás de la barra de estado. Lo haces cambiando tu tema de valores-v21:

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>

Nota: Si se usa un <fragment android:name="fragments.NavigationDrawerFragment"> lugar de

<LinearLayout android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true"> <!-- Your drawer content --> </LinearLayout>

el diseño real, el efecto deseado se logrará si llama a fitsSystemWindows(boolean) en una vista que devuelve del método 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; }


Los enfoques anteriores son correctos y pueden estar funcionando. He creado una demostración funcional siguiendo la guía anterior y probé en 2.xa 5.x

Puedes clonar desde Github

Lo importante para jugar es en Actividad principal

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

y la llamada de vuelta

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

Absolutamente el tema para V21 hace la magia

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

y el ScrimInsetsFrameLayout

Ahora esto es más fácil con la nueva biblioteca de soporte de diseño

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

clon de @Chris Banes https://github.com/chrisbanes/cheesesquare


Prueba con esto:

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

estilo:

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

La actividad principal extiende ActionBarActivity

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

Ahora puedes onCreateOptionsMenu como ActionBar normal con ToolBar.

Este es mi diseño

  • SUPERIOR: Cajón izquierdo - Cajón derecho
    • MID: ToolBar (ActionBar)
    • ABAJO: ListFragment

¡Espero que lo entiendas! ¡Diviértete!


Todas las respuestas mencionadas aquí son demasiado antiguas y extensas. La mejor y más corta solución que funciona con la última navegación es

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

esto va a cambiar el color de la barra de estado a transparente cuando abras el cajón

Ahora, cuando cierre el cajón, debe cambiar el color de la barra de estado nuevamente a oscuro, para que pueda hacerlo de esta manera.

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

y luego en el diseño principal agregue una sola línea, es decir

android:fitsSystemWindows="true"

y el diseño de tu cajón se verá así

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

y su vista de navegación se verá así

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

Lo he probado y funciona completamente. Espero que ayude a alguien. Puede que este no sea el mejor enfoque, pero funciona sin problemas y es fácil de implementar. Marcarlo si ayuda. Codificación feliz :)


Estoy usando la biblioteca de soporte de diseño. Y con solo usar un tema personalizado, logré una barra de estado transparente cuando abrí el cajón de navegación.

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

Finalmente agregue el tema en el archivo de manifiesto

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

No olvide utilizar la propiedad, android:fitsSystemWindows="true" en "DrawerLayout"