When Android 4.4 KitKat was released, everyone was excited to see the new translucent status bar and navigation bar. It adds a whole new level of beauty to the operating system. After seeing Trello implement it so well, I wanted to implement it in my own apps. It took me a while with some research to sort some things out, so I thought I would post how I did it to help others and probably myself again at some point in the future.
The Goal
We will be making the status bar (the black bar on the top of the screen) transparent, along with the navigation bar (the black bar at the bottom of the screen). The main source of my original troubles was trying to make the transparent navigation bar correctly overlap with the ListView and display list items as they scroll under the navigation bar.
Part 1 — Initial Setup
First, we will make the status bar and navigation transparent. You must have two folders inside the /res folder of your project: values and values-v19. Files in the values-19 **folder will be used on API 19 (4.4 KitKat), files in the **valuesfolder will be used on anything below API 19. Then you must create two files, both called styles.xml, one for each values folder; the contents should look similar to what’s shown below.
/values/styles.xml
<?xml version=”1.0″ encoding=”utf-8″?> <resources> <style name=”Theme.TransparencyDemo” parent=”@android:style/Theme.Holo.Light”/> </resources>
/values-v19/styles.xml
<?xml version=”1.0″ encoding=”utf-8″?> <resources> <style name=”Theme.TransparencyDemo” parent=”@android:style/Theme.Holo.Light”> <item name=”android:windowTranslucentStatus”>true</item> <item name=”android:windowTranslucentNavigation”>true</item> </style> </resources>
You then must set the Theme.TransparencyDemo theme to your application through its manifest:
…
…
In the layout containing your list, add two attributes to your ListView:
<?xml version=”1.0″ encoding=”utf-8″?> <ListView xmlns:android=”[http://schemas.android.com/apk/res/android”](http://schemas.android.com/apk/res/android”); android:id=”@android:id/list” android:layout_width=”fill_parent” android:layout_height=”fill_parent” android:fitsSystemWindows=”true” android:clipToPadding=”false”/>
The fitsSystemWindows attribute makes your ListView fit to the edges of the action bar and navigation bar (instead of going under them), and clipToPadding makes items of your ListViews and ScrollViews scroll under the navigation bar (and allows the last item in the list scroll all the way up until it just passes the navigation bar). These attributes can also be added to your actual theme (in /values-v19/styles.xml), but that may not be right for all cases.
Here’s the result of the new theming; the status bar matches the background color of the activity window and the navigation bar is fully transparent:
Part 2 — Status Bar Tint
We now have transparency working as it should, however you’ll notice the status bar doesn’t match the color of the action bar like most would want. That’s because when transparency for the status bar is enabled, it will match the color of the window background which in this case is the color you see displayed in the background of the ListView. One way to solve this is by setting the android:windowBackground attribute in your theme, however this would change the entire background color of your app. I found a useful library, SystemBarTint, that allows you to set the tint color of your status bar.
Once you have the library on your computer and added as a library reference to your project, add something like the following to onCreate() of your main activity. I would recommend using setStatusBarTintResource() instead of explicitly using a color, but this works for the example:
// Only set the tint if the device is running KitKat or above if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { SystemBarTintManager tintManager = new SystemBarTintManager(this); tintManager.setStatusBarTintEnabled(true); // Holo light action bar color is #DDDDDD int actionBarColor = Color.parseColor(“#DDDDDD”); tintManager.setStatusBarTintColor(actionBarColor); }
The result:
Part 3 — Landscape
You’ll notice when you go into landscape on a KitKat device that the navigation bar turns black and overlaps with your content where it shouldn’t. This can be solved using a boolean value that enables or disables translucent navigation based on screen orientation. Create a bools.xml file in /res/values-v19 and in /res/values-land-v19:
/values-v19/bools.xml:
<?xml version=”1.0″ encoding=”utf-8″?> <resources> <bool name=”transparent_nav”>true</bool> </resources>
/values-land-v19/bools.xml:
<?xml version=”1.0″ encoding=”utf-8″?> <resources> <bool name=”transparent_nav”>false</bool> </resources>
Then all you need to do is modify your theme in /values-v19/styles.xml:
<?xml version=”1.0″ encoding=”utf-8″?> <resources> <style name=”Theme.TransparencyDemo” parent=”@android:style/Theme.Holo.Light”> <item name=”android:windowTranslucentStatus”>true</item> <item name=”android:windowTranslucentNavigation”>@bool/transparent_nav</item> </style>
The boolean value will change when your activity’s configuration changes when the screen orientation changes.
Part 4 — Fragment Transactions Messing Up Padding?
Are you using Fragments and FragmentTransactions in your app? Have you noticed that when you go through a fragment transaction, the effect of fitsSystemWindows=”true” goes away and your fragment gets covered by the action bar and the navigation bar? I’ve found a solution to this from the SystemBarTint library we used to set the status bar color.
First, add this method to your Fragment:
public static void setInsets(Activity context, View view) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; SystemBarTintManager tintManager = new SystemBarTintManager(context); SystemBarTintManager.SystemBarConfig config = tintManager.getConfig(); view.setPadding(0, config.getPixelInsetTop(true), config.getPixelInsetRight(), config.getPixelInsetBottom()); }
Now in your Fragment, override onViewCreated() if you haven’t already and make it look like this:
@Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // This could also be a ScrollView ListView list = (ListView) view.findViewById(android.R.id.list); // This could also be set in your layout, allows the list items to scroll through the bottom padded area (navigation bar) list.setClipToPadding(false); // Sets the padding to the insets (include action bar and navigation bar padding for the current device and orientation) setInsets(list); }
This will set the padding of the ListView in your Fragment to be below the action bar and status bar, and above the navigation bar if the device has one. Setting clipToPadding to false allows last item in the ListView to scroll up above the navigation bar, but you can see all the list items as they go under the transparent navigation bar.
NOTE: you will probably wanna set fitsSystemWindows=”true” to the empty text and/or progress view of your fragment layout so they center in your layout as they should.
Wrapping Up
Want to see this demo in action on your phone? Get the code and APK file from this repository.
********************************************************************************************************************
下面的方式可以不用使用第三方library
转自: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1117/1992.html
Android 从 4.4(KitKat) 开始提供了一个视觉上的提升,让最上方的状态栏 (Status Bar) 以及最下方的导航栏 (Navigation Bar) 可以被透明化,并让 APP 的内容可以往上下延伸,使整个画面的可被利用度大幅提升。
从 3.0 (honeycomb) 开始,Navigation Bar采用虚拟键,一直都占据一块不小的空间,对很多人来说,整个屏幕无法充利用,是一件相当痛苦的事情。也因此,有些人会刻意去挑选仍维持着实体键设计的手机。
而 Google 似乎也意识到这个状况,从 4.4 (KitKat) 提供了开发者一个新的作法,让我们可以把导航栏 (Navigation Bar)给透明化,并让内容延伸到该处,甚至是状态列 (Status Bar) 也可以被设定透明,这样再搭配 Action Bar 的配色,可以像上图一般,让整个 APP 更显得一致。
那我们就看看是如何实现的吧:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = getWindow(); // Translucent status bar window.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // Translucent navigation bar window.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); }
的确,代码就是这么短,一行设定Status Bar、一行设定Navigation Bar 。
别忘了判断一下版本。确保4.4以下不会报错。
再来,有个部份要稍微留意一下,如果不希望 APP 的内容被上拉到状态列 (Status bar) 的话,要记得在介面 (Layout) XML 档中,最外面的那层,要再加上一个属性 fitsSystemWindows为true ,请见下方
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".MainActivity" > <!-- Content --> </RelativeLayout>
在界面的根层加入 android:fitsSystemWindows=”true” 这个属性,这样就可以让内容界面从 Action Bar 下方开始。
再来,若我们的 APP 可以从 4.4 (KitKat) 开始支持,那其实可以直接从 style 去进行设定,我们可以在官网上看到对透明化的说明里,官方提供了两种 no title 的主题风格可以让我们使用,分别如下
Theme.Holo.Light.NoActionBar.TranslucentDecor
Theme.Holo.NoActionBar.TranslucentDecor
这样我们就可以做出全屏幕的APP。
如果我们希望可以维持Action Bar的存在,那只需要继承一般的主题,并在主题中分别加入两个属性值即可
<style name="AppTheme" parent="AppBaseTheme"> <!-- Status Bar --> <item name="android:windowTranslucentStatus">true</item> <!-- Navigation Bar --> <item name="android:windowTranslucentNavigation">true</item> </style>
跟java代码方式一样,也是两行完成,上面一行是设定Status Bar、下面一行是设定Navigation Bar 。别忘了,如果不希望内容被 Action Bar 压住,那先前提及的 Layout 属性 android:fitsSystemWindows=”true” 要设置到。
其实以现在的状况来说,通过java代码方式去设定是最安全的,毕竟目前绝大部份的装置都还未被升级到 4.4 (KitKat)。