天天看點

沉浸式狀态欄的實作

android5.0推出了沉浸式狀态欄的效果,讓android狀态欄可以輕松的改變顔色,大大提升app的一個視覺效果,相信android開發者們都已經早就接觸并實作過該效果了,最近剛好有時間,将自己的一個實作記錄下來;沉浸式效果在android5.0+上面實作起來還是比較簡單,但是要在android4.4-android5.0上面實作的還是要費點事情,目前還沒有看到android4.4以下實作了該效果,是以在開發中隻需做android5.0+和android4.4-android5.0一個相容;

android5.0+沉浸式效果的實作

方法一:

<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorAccent</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
           

修改colorPrimaryDark的顔色就可以實作沉浸式的效果,不過需要注意的是修改colorPrimaryDark的顔色意味着所有的頁面都是修改的顔色,如果某個頁面想實作不一樣的沉浸式效果,需要做特别處理;

方法二:

調用系統的setStatusBarColor方法;

注意:在使用的時候會提示該方法是在api21才會有;

方法三:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
                <!-- Customize your theme here. -->
                <item name="colorPrimary">@color/colorPrimary</item>
                <item name="colorPrimaryDark">@color/colorPrimary</item>
                <item name="colorAccent">@color/colorAccent</item>
                <item name="android:statusBarColor">@color/colorAccent</item>
        </style>
           

在樣式裡面添加android:statusBarColor,同樣android:statusBarColor是在api21以後才會有,所有要建立一個values-v21的檔案,并添加樣式;

不管哪種方法,在android5.0+上面基本上一句代碼就可以實作沉浸式的效果,但是當你把上面這些代碼運作到android5.0以下的手機上的時候什麼效果都不會有,是以要在上面的基礎上做相應的相容,下面就寫下如果去相容android4.4到android5.0;

對于android4.4到android5.0的思路是:首先把他弄成全屏,在狀态欄的部分加一個布局

/**
     * 設定狀态欄顔色
     * @param activity  對應的activity
     * @param color  設定的顔色
     */
    public static void setStatusBarColor(Activity activity,int color){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            //android5+
            //直接調用系統提供的方法  setStatusBarColor
            activity.getWindow().setStatusBarColor(color);
        }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
            //android4-android5
            //設定成全屏
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //在狀态欄的部分添加一個布局
            View view=new View(activity);
            ViewGroup.LayoutParams params=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight(activity));
            view.setLayoutParams(params);
            view.setBackgroundColor(color);

            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            decorView.addView(view);

            //擷取activity中setContentView布局的根布局
            ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
            View childAt = contentView.getChildAt();
            childAt.setFitsSystemWindows(true);
        }
    }
           

在擷取狀态欄高度的時候可以通過反射擷取,也可以通過另外一種方式擷取;

方式一:

/**
     * 擷取狀态欄的高度
     * @param activity  對應的activity
     * @return  狀态欄的高度
     */
    private static int getStatusBarHeight(Activity activity) {
        Resources resources = activity.getResources();
        int identifier = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelOffset(identifier);
    }
           

方式二(反射):

/**
     * 反射擷取狀态欄高度
     * @param context  上下文
     * @return  狀态欄高度
     */
    private static int getStatusBarHeight(Activity context){
        // 反射手機運作的類:android.R.dimen.status_bar_height.
        int statusHeight = -;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            String heightStr = clazz.getField("status_bar_height").get(object).toString();
            int height = Integer.parseInt(heightStr);
            //dp--->px
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }
           

這樣子沉浸式狀态欄效果就實作了:

android6.0效果:

沉浸式狀态欄的實作

android4.4.2效果:

沉浸式狀态欄的實作

底部導航欄沉浸式效果的實作和上面的實作大緻是一樣的;

android5.0+的實作:

方法一:

建立一個values-v21的檔案,在style樣式中添加android:navigationBarColor

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
                <!-- Customize your theme here. -->
                <item name="colorPrimary">@color/colorPrimary</item>
                <item name="colorPrimaryDark">@color/colorPrimary</item>
                <item name="colorAccent">@color/colorAccent</item>
                <item name="android:navigationBarColor">@color/colorAccent</item>
        </style>
           

方法二:

調用系統的setNavigationBarColor方法;

android4.4-android5.0的相容:

在布局檔案添加一個view,設定虛拟導航欄為透明,設定view的高度為底部導航欄的高度,并設定view的顔色;

/**
     * 設定底部導航顔色
     * @param activity  上下文
     * @param color  設定的顔色
     * @param view  底部的view
     */
    public static void setNavigationColor(Activity activity,int color,View view){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            //android5.0+
            //直接調用系統提供的方法  setStatusBarColor
            activity.getWindow().setNavigationBarColor(color);
        }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
            //android4.4-android5.0
            if(view!=null){
                //設定成全屏
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                //判斷底部虛拟導航欄是否存在(或者開啟)
                if(hasNavigationBarShow(activity.getWindowManager())){
                    ViewGroup.LayoutParams p = view.getLayoutParams();
                    p.height+=getNavigationBarHeight(activity);
                    view.setLayoutParams(p);
                    view.setBackgroundColor(color);
                }else{
                    ViewGroup.LayoutParams p = view.getLayoutParams();
                    p.height=;
                    view.setLayoutParams(p);
                }
            }
        }
    }
           

這裡需要注意的是要判斷底部導航欄是否存在,在有些手機上是沒有底部導航欄,有些手機上即使有底部導航欄,也可以設定關閉底部導航欄,在設定的時候需要判斷;

/**
     * 判斷底部虛拟導航欄是否存在(打開)
     * @param windowManager
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    private static boolean hasNavigationBarShow(WindowManager windowManager) {
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics outMetrics=new DisplayMetrics();
        //擷取整個螢幕的高度
        display.getRealMetrics(outMetrics);
        int heightPixels = outMetrics.heightPixels;
        int widthPixels = outMetrics.widthPixels;
        //擷取内容展示部分的高度
        outMetrics=new DisplayMetrics();
        int heightPixels1 = outMetrics.heightPixels;
        int widthPixels1 = outMetrics.widthPixels;
        int h=heightPixels-heightPixels1;
        int w=widthPixels-widthPixels1;
        return w>||h>;

    }
           

擷取底部導航欄的高度和上面擷取導航欄的高度差不多;

/**
     * 擷取底部導航欄高度
     * @param activity  上下文
     * @return 底部導航欄高度
     */
    private static int getNavigationBarHeight(Activity activity) {
        Resources resources = activity.getResources();
        int identifier = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        return resources.getDimensionPixelOffset(identifier);
    }
           

這樣就實作底部導航欄沉浸式效果了;

android6.0效果:

沉浸式狀态欄的實作

android4.4.2效果:

沉浸式狀态欄的實作

源碼位址:

http://download.csdn.net/download/wangwo1991/9928577

繼續閱讀