跳到主要內容

如何把 Status Bar 變透明

        Android 從 4.4 (KitKat, api level 19) 後才支援這個功能, 到了 5.0 (Lollipop, api level 21) 自訂性更高, 可以讓我們設定各種顏色, 當然也包含透明色。以下分別介紹如何使用這兩種版本的方法。

       方法1: 利用 attribute "android:windowTranslucentStatus", 在 style.xml 加上這個 attribute 就好。要注意的是 Android 版本要在 4.4 以上才可以用這個 attribute:

<resources>

    <!--
        Base application theme for API 19+. This theme completely replaces
        AppTheme from res/values/styles.xml on API 19+ devices.
    -->
    <style name="AppTheme" parent="@style/AppBaseTheme">
        <!-- API 19 theme customizations can go here. -->
        <item name="android:windowTranslucentStatus">true</item>
    </style>

</resources>
        下面的圖分別為 4.4 跟 5.0 的手機使用這個 attribute 的結果:


        因為設定了這個 attribute, 畫面會從 status bar 下方開始畫。要解決這個有兩種方法, 第一個是在 layout 畫面設定 attribute "android:fitsSystemWindows"

<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:background="@color/colorPrimary"
    android:fitsSystemWindows="true"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:textColor="@android:color/black" />

</RelativeLayout>



        有時候你的 layout 可能很複雜, 不一定能單純用這個 attribute 就解決, 這時候就要用第二種方法: 用程式去算 status bar 的 height, 把想往下移的 layout 都加上 status bar 的高。網路上有提供如何取得 status bar height 的範例程式碼:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    } 
    return result;
}

        當然這也可以用程式碼的方式去控制, 在 Activity 使用以下的 api:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window w = this.getWindow();
    w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}

        用程式控制一樣會有 layout 從 status bar 開始的問題, 要記得用上面的方法避掉。

        方法2: 使用 Android 5.0 新加的 attribute android:colorPrimaryDark (或是 support library v7 appcompat 的 colorPrimaryDark)。根據官方說法, colorPrimaryDark 就是會設定 status bar 的顏色, 要直接改 status bar 的顏色也可以設定 attribute android:statusBarColor。但是目前查到修改 xml 的方式都不能讓 status bar 變透明, 只能透過程式碼去設定:
public abstract void setStatusBarColor (int color), 而官方也有說, 要讓 status bar 變透明, 不能只單純用這個 api, 還需要另外設定一些 flag 才行。以下為範例程式碼:

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Window window = this.getWindow();

    // Followed by google doc.
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(ContextCompat.getColor(this, android.R.color.transparent));

    // For not opaque(transparent) color.
    window.getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}


        上圖為用方法2的結果, 可以看出還是會有跟方法1一樣的問題, 因此不想畫面跟 status bar 重疊的話, 一樣可以用上面說的方法解決。

參考資料:

1. stack overflow - Height of status bar in Android
5. Android developers - Using the Material Theme
6. Android documentation - Window.setStatusBarColor(int)
7. 莫希爾(Mosil)手札 - 在 KITKAT 以上版本的 TRANSLUCENT 介紹

這個網誌中的熱門文章

在 Fragment 裡使用 ViewPager 搭配 FragmentPagerAdapter

Fragment 是個強大的東西,可以想成 Activity 的子頁面,可隨時替換頁面內容(但使用起來還滿麻煩的…)。這麼強大的東西,在 ViewPager 當然也會提供 Fragment 的版本。在官方文件就有一個 PagerAdapter 的實作:FragmentPagerAdapter,可以用 Fragment 來當成每個 ViewPager 的子頁。FragmentPagerAdapter 的官方文件中也有提供 sample code。

        但我自己參考 sample code 寫出來的效果卻怪怪的,ViewPager 裡子頁面的 lifecycle 竟然沒有跟著父 Fragment ,看起來比較像是跟著 Activity。仔細看 sample code 才發現,它是在 Activity 裡使用 ViewPager + FragmentPagerAdapter。那要如何使用在 Fragment 呢?

        其實只要改一行 code 就可以了。 sample code 裡的
mAdapter = new MyAdapter(getSupportFragmentManager()); 只要改成
mAdapter = new MyAdapter(Fragment.getChildFragmentManager()); 就可以囉 ~~

        由於 getChildFragmentManager() api level 17+ 才有的東西,而 Fragment 是 11+ 才有,不想定太高的 api level 可以使用 support v4 library,怎麼使用就不多說啦。

參考資料:

support v4 Fragment:
http://developer.android.com/intl/zh-tw/reference/android/support/v4/app/Fragment.html

support v4  FragmentPagerAdapter:
http://developer.android.com/intl/zh-w/reference/android/support/v4/app/FragmentPagerAdapter.html


透明背景的 AlertDialog

Android dialog 預設都會有一個背景底色,要怎麼把它去掉呢?其實直接改 AlertDialog 的 style 就可以了,但我改好久…以下的範例是使用了 Support v7 AppCompat 的 theme,其他 theme 我不知道可不可以,有興趣的人可以試試看。

<style name="TransparentDialog" parent="@style/Base.Theme.AppCompat.Dialog"> <item name="android:windowFrame">@null</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsFloating">true</item> <item name="android:windowTitleStyle">@null</item> <item name="android:background">@android:color/transparent</item> <item name="android:windowNoTitle">true</item> <item name="android:alertDialogStyle">@style/TransparentDialog.Color</item> </style> <style name="TransparentDialog.Color" parent="@style/Base.Theme.AppCompat.Dialog"> <item name="android:…