Estou trabalhando no projeto Android e implementando o Navigation Drawer. Estou lendo as novas especificações de design de material e a lista de verificação de design de material .
A especificação diz que o painel deslizante deve flutuar acima de tudo, incluindo a barra de status, e ser semitransparente sobre a barra de status.
Meu painel de navegação está sobre a barra de status, mas não tem nenhuma transparência. Segui o código deste post SO, conforme sugerido no blog de desenvolvedores do Google, link acima. Como faço para usar DrawerLayout para exibir na ActionBar / Toolbar e na barra de status? .
Abaixo está o meu layout XML
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/my_awesome_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="@color/appPrimaryColour" />
</LinearLayout>
<LinearLayout android:id="@+id/linearLayout"
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true"
android:background="#ffffff">
<ListView android:id="@+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"></ListView>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
Abaixo está o tema do meu aplicativo
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/appPrimaryColour</item>
<item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
<item name="colorAccent">@color/appPrimaryColour</item>
<item name="windowActionBar">false</item>
<item name="windowActionModeOverlay">true</item>
</style>
Abaixo está o tema do meu apps v21
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/appPrimaryColour</item>
<item name="colorPrimaryDark">@color/appPrimaryColourDark</item>
<item name="colorAccent">@color/appPrimaryColour</item>
<item name="windowActionBar">false</item>
<item name="windowActionModeOverlay">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
Abaixo está o meu método onCreate
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
mDrawerLayout = (DrawerLayout)findViewById(R.id.my_drawer_layout);
mDrawerList = (ListView)findViewById(R.id.left_drawer);
mDrawerLayout.setStatusBarBackgroundColor(
getResources().getColor(R.color.appPrimaryColourDark));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
LinearLayout linearLayout =
(LinearLayout)findViewById(R.id.linearLayout);
linearLayout.setElevation(30);
}
Abaixo está uma captura de tela da minha gaveta de navegação mostrando que a parte superior não é semitransparente
Respostas:
O fundo da sua barra de status é branco, o fundo da sua gaveta
LinearLayout
. Por quê? Vocês são configuraçõesfitsSystemWindows="true"
para vocêDrawerLayout
e paraLinearLayout
dentro dele. Isso faz com que seuLinearLayout
se expanda atrás da barra de status (que é transparente). Assim, torna o fundo da gaveta parte da barra de status branco.Se você não quiser que sua gaveta se estenda para trás da barra de status (deseja ter um fundo semitransparente para toda a barra de status), você pode fazer duas coisas:
1) Você pode simplesmente remover qualquer valor de fundo de seu
LinearLayout
e colorir o fundo de seu conteúdo dentro dele. Ou2) Você pode remover
fitsSystemWindows="true"
do seuLinearLayout
. Acho que essa é uma abordagem mais lógica e mais limpa. Você também evitará que uma sombra seja projetada sob a barra de status, onde sua gaveta de navegação não se estende.Se você deseja que sua gaveta se estenda atrás da barra de status e tenha uma sobreposição semitransparente do tamanho da barra de status, você pode usar um
ScrimInsetFrameLayout
como um contêiner para o conteúdo da sua gaveta (ListView
) e definir o plano de fundo da barra de status usandoapp:insetForeground="#4000"
. Claro, você pode mudar#4000
para o que quiser. Não se esqueça de ficarfitsSystemWindows="true"
aqui!Ou se você não quiser sobrepor seu conteúdo e exibir apenas uma cor sólida, você pode apenas definir o plano de fundo de sua
LinearLayout
preferência. Não se esqueça de definir o plano de fundo do seu conteúdo separadamente!EDIT: Você não precisa mais lidar com nada disso. Consulte a Biblioteca de Suporte de Design para uma implementação de Gaveta / Visualização de Navegação mais fácil.
fonte
Tudo que você precisa fazer é usar alguma cor semitransparente para a barra de status. Adicione estas linhas ao seu tema v21:
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@color/desired_color</item>
Não se esqueça de que o
color
(recurso) deve sempre estar no formato de#AARRGGBB
. Isso significa que a cor também incluirá o valor alfa.fonte
Por que não usar algo semelhante a isso?
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent"/> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" android:background="#80111111"/> </android.support.v4.widget.DrawerLayout>
O código acima usa o recurso alfa no
android:background
para poder mostrar transparência na barra de ações.Existem outras maneiras de fazer isso por meio de código, como mostram outras respostas. Minha resposta acima, faz o necessário no arquivo de layout xml, que na minha opinião é facilmente editado.
fonte
Todas as respostas mencionadas aqui são muito antigas e longas. A melhor e mais curta solução que funciona com o mais recente 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); } }
isso vai mudar a cor da sua barra de status para transparente quando você abrir a gaveta
Agora, ao fechar a gaveta, você precisa alterar a cor da barra de status novamente para escuro. Portanto, você pode fazer isso desta forma.
@Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); try { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { // Do something for lollipop and above versions Window window = getWindow(); // clear FLAG_TRANSLUCENT_STATUS flag: window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // finally change the color again to dark window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark)); } } catch (Exception e) { Crashlytics.logException(e); } }
e, em seguida, no layout principal, adicione uma única linha, ou seja,
android:fitsSystemWindows="true"
e o layout da sua gaveta ficará como
<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">
e sua visualização de navegação parecerá
<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" />
Eu testei e está funcionando perfeitamente. Espero que ajude alguém. Esta pode não ser a melhor abordagem, mas funciona bem e é simples de implementar. Marque se ajudar. Boa codificação :)
fonte
Você precisa envolver o layout da gaveta de navegação dentro de um
ScrimLayout
.A
ScrimLayout
basicamente desenha um retângulo semitransparente sobre o layout da gaveta de navegação. Para recuperar o tamanho da inserção, simplesmente substituafitSystemWindows
em seuScrimLayout
.@Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); return true; }
Substituição posterior
onDraw
para desenhar um retângulo semitransparente.Um exemplo de implementação pode ser encontrado na fonte do Google IO App. Aqui você pode ver como ele é usado no layout xml.
fonte
Se desejar, o painel de navegação está sobre a barra de status e semitransparente sobre a barra de status. Google I / O Android App Source oferece uma boa solução ( APK na Play Store não é atualizado para a última versão)
Primeiro você precisa de um ScrimInsetFrameLayout
/* * Copyright 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * A layout that draws something in the insets passed to {@link #fitSystemWindows(Rect)}, i.e. the area above UI chrome * (status and navigation bars, overlay action bars). */ public class ScrimInsetsFrameLayout extends FrameLayout { private Drawable mInsetForeground; private Rect mInsets; private Rect mTempRect = new Rect(); private OnInsetsCallback mOnInsetsCallback; public ScrimInsetsFrameLayout(Context context) { super(context); init(context, null, 0); } public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrimInsetsView, defStyle, 0); if (a == null) { return; } mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsView_insetForeground); a.recycle(); setWillNotDraw(true); } @Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); setWillNotDraw(mInsetForeground == null); ViewCompat.postInvalidateOnAnimation(this); if (mOnInsetsCallback != null) { mOnInsetsCallback.onInsetsChanged(insets); } return true; // consume insets } @Override public void draw(Canvas canvas) { super.draw(canvas); int width = getWidth(); int height = getHeight(); if (mInsets != null && mInsetForeground != null) { int sc = canvas.save(); canvas.translate(getScrollX(), getScrollY()); // Top mTempRect.set(0, 0, width, mInsets.top); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Bottom mTempRect.set(0, height - mInsets.bottom, width, height); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Left mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Right mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); canvas.restoreToCount(sc); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(this); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(null); } } /** * Allows the calling container to specify a callback for custom processing when insets change (i.e. when * {@link #fitSystemWindows(Rect)} is called. This is useful for setting padding on UI elements based on * UI chrome insets (e.g. a Google Map or a ListView). When using with ListView or GridView, remember to set * clipToPadding to false. */ public void setOnInsetsCallback(OnInsetsCallback onInsetsCallback) { mOnInsetsCallback = onInsetsCallback; } public static interface OnInsetsCallback { public void onInsetsChanged(Rect insets); } }
Então, em seu layout XML, altere esta parte
<LinearLayout android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" android:background="#ffffff"> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice"></ListView> </LinearLayout>
Altere LinearLayout para ScrimInsetFrameLayout assim
<com.boardy.util.ScrimInsetFrameLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/linearLayout" android:layout_width="304dp" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" app:insetForeground="#4000"> <ListView android:id="@+id/left_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice"></ListView> </com.boardy.util.ScrimInsetFrameLayout>
fonte
ScrimInsetsView_insetForeground
atributo.android.support.design.internal.ScrimInsetsFrameLayout
da biblioteca de suporteTive um recurso semelhante para implementar em meu projeto. E para deixar minha gaveta transparente, eu só uso a transparência para cores hexadecimais . Usando 6 dígitos hexadecimais, você tem 2 dígitos hexadecimais para cada valor de vermelho, verde e azul, respectivamente. mas se você colocar dois dígitos adicionais (8 dígitos hexadecimais), você terá ARGB (dois dígitos para o valor alfa) ( veja aqui ).
Aqui estão os valores de opacidade hexadecimal: para os 2 dígitos adicionais
100% — FF 95% — F2 90% — E6 85% — D9 80% — CC 75% — BF 70% — B3 65% — A6 60% — 99 55% — 8C 50% — 80 45% — 73 40% — 66 35% — 59 30% — 4D 25% — 40 20% — 33 15% — 26 10% — 1A 5% — 0D 0% — 00
Por exemplo: se você tem a cor hexadecimal (# 111111) basta colocar um dos valores de opacidade para obter transparência. assim: (# 11111100)
Minha gaveta não cobre a barra de ação (como a sua) mas a transparência pode ser aplicada nesses casos também. Este é meu código:
<ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#11111100" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" /> </android.support.v4.widget.DrawerLayout>
E aqui está outro artigo que pode ajudá-lo a entender os códigos alfa em cores hexadecimais.
fonte
As soluções existentes estão bastante desatualizadas. Aqui está a solução mais recente que deve funcionar perfeitamente em bibliotecas AndroidX ou de materiais.
Adicione
android:fitsSystemWindows="true"
à visualização raiz do seu layout, que é DrawerLayout para o seu caso.Isso diz ao modo de exibição para usar a tela inteira para medição e layout, sobrepondo-se à barra de status.
Adicione o seguinte ao seu estilo XML
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowTranslucentStatus">true</item>
windowTranslucentStatus
tornará a barra de status transparente,windowDrawsSystemBarBackgrounds
informa a barra de status para desenhar qualquer coisa abaixo dela, em vez de ser um vazio preto.Ligue
DrawerLayout.setStatusBarBackground()
ouDrawerLayout.setStatusBarBackgroundColor()
em sua atividade principalIsso diz ao DrawerLayout para colorir a área da barra de status.
fonte
Acima de umas boas soluções, mas não funcionaram no meu caso,
meu caso: a barra de status tem cor amarela definida já usando estilos, não é translúcida. e a cor da minha gaveta de navegação é branco, agora sempre que eu desenho minha gaveta de navegação, ela está sempre atrás da barra de status e da barra de navegação também, já que a cor da barra de navegação também é definida.
objetivo: alterar a barra de status e a cor da barra de navegação quando a gaveta de navegação for aberta e restaurá-la quando for fechada.
solução:
binding.drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { } @Override public void onDrawerOpened(@NonNull View drawerView) { getWindow().setStatusBarColor(getResources().getColor(R.color.forground)); getWindow().setNavigationBarColor(getResources().getColor(R.color.forground)); } @Override public void onDrawerClosed(@NonNull View drawerView) { getWindow().setStatusBarColor(getResources().getColor(R.color.yellow)); getWindow().setNavigationBarColor(getResources().getColor(R.color.yellow)); } @Override public void onDrawerStateChanged(int newState) { } });
fonte
Todas as respostas aqui são muito complicadas, deixe-me fornecer um código simples e direto. No estilo AppTheme, adicione esta linha de código e você obterá uma barra de status cinza semitransparente ao abrir a gaveta.
<item name="android:windowTranslucentStatus">true</item>
isso fará com que funcione.
fonte