Saya sedang mengerjakan proyek Android dan saya mengimplementasikan Navigation Drawer. Saya membaca Spesifikasi Desain Material baru dan Daftar Periksa Desain Material .
Spesifikasi mengatakan bahwa panel geser keluar harus mengapung di atas segalanya termasuk bilah status dan semi-transparan di atas bilah status.
Panel navigasi saya berada di atas bilah status tetapi tidak ada transparansi apa pun. Saya telah mengikuti kode dari ini posting SO seperti yang disarankan di tempat blog pengembang Google, tautan di atas Bagaimana cara menggunakan DrawerLayout untuk ditampilkan di atas ActionBar / Toolbar dan di bawah bilah status? .
Di bawah ini adalah tata letak XML saya
<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>
Di bawah ini adalah tema aplikasi saya
<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>
Di bawah ini adalah tema apps v21 saya
<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>
Di bawah ini adalah metode onCreate saya
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);
}
Di bawah ini adalah tangkapan layar dari panel samping navigasi saya yang menunjukkan bahwa bagian atas tidak semi transparan
Jawaban:
Latar belakang bilah status Anda berwarna putih, latar belakang laci Anda
LinearLayout
. Mengapa? Anda adalah pengaturanfitsSystemWindows="true"
untuk AndaDrawerLayout
dan bagianLinearLayout
dalamnya. Ini menyebabkan AndaLinearLayout
meluas di belakang bilah status (yang transparan). Dengan demikian, membuat latar belakang untuk bagian laci bilah status berwarna putih.Jika Anda tidak ingin laci Anda diperpanjang di belakang bilah status (ingin memiliki latar belakang semi-transparan untuk seluruh bilah status), Anda dapat melakukan dua hal:
1) Anda cukup menghapus nilai latar belakang apa pun dari Anda
LinearLayout
dan mewarnai latar belakang konten Anda di dalamnya. Atau2) Anda dapat menghapus
fitsSystemWindows="true"
fileLinearLayout
. Saya pikir ini adalah pendekatan yang lebih logis dan lebih bersih. Anda juga akan menghindari bayangan yang dilemparkan di bawah bilah status, di mana laci navigasi Anda tidak meluas.Jika Anda ingin laci Anda diperpanjang di belakang bilah status dan memiliki hamparan semi-transparan berukuran bilah status, Anda dapat menggunakan a
ScrimInsetFrameLayout
sebagai wadah untuk konten laci Anda (ListView
) dan menyetel latar belakang bilah status menggunakanapp:insetForeground="#4000"
. Tentu saja, Anda dapat mengubah#4000
apa pun yang Anda inginkan. Jangan lupa simpanfitsSystemWindows="true"
disini!Atau jika Anda tidak ingin menampilkan konten Anda dan hanya menampilkan warna solid, Anda dapat mengatur latar belakang Anda
LinearLayout
sesuai keinginan. Jangan lupa untuk mengatur latar belakang konten Anda secara terpisah!EDIT: Anda tidak perlu lagi berurusan dengan semua ini. Silakan lihat Design Support Library untuk mengetahui penerapan Navigasi Drawer / View yang lebih mudah.
sumber
Yang perlu Anda lakukan adalah menggunakan beberapa warna semi-transparan untuk bilah status. Tambahkan baris ini ke tema v21 Anda:
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@color/desired_color</item>
Jangan lupa bahwa
color
(resource) harus selalu dalam format#AARRGGBB
. Artinya warna tersebut juga akan menyertakan nilai alpha.sumber
Mengapa tidak menggunakan sesuatu yang mirip dengan ini?
<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>
Kode di atas menggunakan sumber daya alfa
android:background
untuk dapat menampilkan transparansi dalam bilah tindakan.Ada cara lain untuk melakukan ini melalui kode, seperti yang ditunjukkan oleh jawaban lain. Jawaban saya di atas, apakah perlu file layout xml yang menurut saya mudah diedit.
sumber
Semua jawaban yang disebutkan di sini terlalu tua dan panjang. Solusi terbaik dan singkat yang bekerja dengan Navigationview terbaru adalah
@Override public void onDrawerSlide(View drawerView, float slideOffset) { super.onDrawerSlide(drawerView, slideOffset); try { //int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ // Do something for lollipop and above versions Window window = getWindow(); // clear FLAG_TRANSLUCENT_STATUS flag: window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); // finally change the color to any color with transparency window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDarktrans));} } catch (Exception e) { Crashlytics.logException(e); } }
ini akan mengubah warna bilah status Anda menjadi transparan saat Anda membuka laci
Sekarang ketika Anda menutup laci Anda perlu mengubah warna bilah status lagi menjadi gelap. Jadi Anda bisa melakukannya dengan cara ini.
@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); } }
dan kemudian di tata letak utama tambahkan satu baris yaitu
android:fitsSystemWindows="true"
dan tata letak laci Anda akan terlihat seperti ini
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="match_parent">
dan tampilan navigasi Anda akan terlihat
<android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/navigation_header" app:menu="@menu/drawer" />
Saya telah mengujinya dan berfungsi penuh, semoga dapat membantu seseorang. Ini mungkin bukan pendekatan terbaik tetapi berfungsi dengan lancar dan mudah diterapkan. Tandai jika membantu. Selamat membuat kode :)
sumber
Anda perlu membungkus tata letak panel navigasi di dalam file
ScrimLayout
.A
ScrimLayout
pada dasarnya menggambar persegi panjang semi transparan di atas tata letak laci navigasi Anda. Untuk mengambil ukuran inset, cukup timpafitSystemWindows
di fileScrimLayout
.@Override protected boolean fitSystemWindows(Rect insets) { mInsets = new Rect(insets); return true; }
Kemudian timpa
onDraw
untuk menggambar persegi panjang semi transparan.Sebuah contoh implementasi dapat ditemukan dalam sumber Google IO App. Di sini Anda dapat melihat bagaimana itu digunakan dalam layout xml.
sumber
Jika Anda ingin panel navigasi berada di atas bilah status dan semi-transparan di atas bilah status. Sumber Aplikasi Android Google I / O memberikan solusi yang baik ( APK di Play Store tidak diperbarui ke versi terakhir)
Pertama, Anda membutuhkan 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); } }
Kemudian, dalam layout XML Anda, ubah bagian ini
<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>
Ubah LinearLayout menjadi ScrimInsetFrameLayout Anda seperti ini
<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>
sumber
ScrimInsetsView_insetForeground
atributnya.android.support.design.internal.ScrimInsetsFrameLayout
dari pustaka dukunganSaya memiliki fitur serupa untuk diterapkan dalam proyek saya. Dan untuk membuat laci saya transparan, saya hanya menggunakan transparansi untuk warna hex . Menggunakan 6 digit hex, Anda memiliki 2 digit hex untuk setiap nilai merah, hijau dan biru. tetapi jika Anda memasukkan dua digit tambahan (8 digit hex), maka Anda memiliki ARGB (dua digit untuk nilai alpha) ( Lihat di sini ).
Berikut adalah Hex Opacity Values: untuk 2 digit tambahan
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
Sebagai contoh: jika Anda memiliki warna de hex (# 111111) cukup masukkan salah satu nilai opacity untuk mendapatkan transparansi. seperti ini: (# 11111100)
Laci saya tidak menutupi panel tindakan (seperti milik Anda) tetapi transparansi dapat diterapkan dalam kasus ini juga. Ini kode saya:
<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>
Dan berikut adalah artikel lain yang dapat membantu Anda memahami kode alfa dalam warna hex.
sumber
Solusi yang ada sudah cukup usang. Inilah solusi terbaru yang seharusnya berfungsi dengan sempurna di AndroidX atau pustaka Material.
Tambahkan
android:fitsSystemWindows="true"
ke tampilan root dari layout Anda, yang merupakan DrawerLayout untuk kasus Anda.Ini memberitahu View untuk menggunakan seluruh layar untuk mengukur & tata letak, tumpang tindih dengan status bar.
Tambahkan berikut ini ke gaya XML Anda
<item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowTranslucentStatus">true</item>
windowTranslucentStatus
akan membuat bilah status transparanwindowDrawsSystemBarBackgrounds
memberi tahu bilah status untuk menggambar apa pun di bawahnya alih-alih menjadi kehampaan hitam.Panggilan
DrawerLayout.setStatusBarBackground()
atauDrawerLayout.setStatusBarBackgroundColor()
dalam Aktivitas utama AndaIni memberitahu DrawerLayout untuk mewarnai area status bar.
sumber
Semua jawaban di sini sangat rumit, izinkan saya memberi Anda kode sederhana langsung. Di bawah gaya AppTheme Anda, tambahkan baris kode ini dan Anda akan mendapatkan bilah status semi transparan abu-abu saat Anda membuka laci.
<item name="android:windowTranslucentStatus">true</item>
ini akan membuatnya berhasil.
sumber
Di atas solusi bagus, tetapi tidak berhasil dalam kasus saya,
kasus saya: bilah status memiliki set warna kuning sudah menggunakan gaya, tidak tembus cahaya. dan warna panel navigasi saya putih, sekarang setiap kali saya menggambar panel samping navigasi saya, ia selalu berada di belakang bilah status dan bilah navigasi juga, karena warna bilah navigasi juga disetel.
tujuan: untuk mengubah bilah status dan warna bilah navigasi saat panel samping navigasi dibuka dan mengembalikannya saat ditutup.
solusi:
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) { } });
sumber