1. 程式人生 > >Android全屏沉浸式應用

Android全屏沉浸式應用

一、概念

首先讓我們看一下預設狀態列的顯示效果 以下以微信與qq為例:

這裡寫圖片描述

由於Android 系統自4.2 開始 UI 上就沒多大改變,而4.4增加了透明狀態列與導航欄的功能如以下圖的效果。

這裡寫圖片描述

從以上的圖可以看出Activity的contentView( 即setContentView設定的檢視)可以延伸到statusBar下方 這種體驗就叫沉浸式體驗。這個是從使用者的角度來感受的。如果從設計師的角度來看就是Immersive Mode 全浸模式,Translucent Bars 半透明狀態列。不同共同的特點就是“將佈局內容延伸到手機狀態列”。

對於這種顯示效果又有以下兩種模式

1、全屏( ContentView 可以進入狀態列)

這裡寫圖片描述

2、非全屏 ( ContentView 與狀態列分離, 狀態列直接著色

這裡寫圖片描述

二、案例分析

sdk5.x以上 ,準備5.0模擬器

非全螢幕:theme預設主題著色狀態列

根據5.0以上的theme配置要求。只需配置colorPirmary(標題欄顏色),colorPrimaryDark(手機狀態列顏色)即可.

在values/styles.xml建立主題

<resources>
    <!--應用的基本主題 -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"
>
<!-- 自定義應用主題 --> <!--標題顏色--> <item name="colorPrimary">@color/colorPrimary</item> <!--狀態列顏色--> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!--text /checkBox顏色--> <item name="colorAccent"
>@color/colorAccent</item>
</style> </resources>

在systembar/src/main/AndroidManifest.xml引用

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <!-這裡是activity ->
</application>

執行效果

這裡寫圖片描述

非全螢幕:Javacode著色狀態列

程式碼位置:com.example.systembar.CodeActivity
1、先寫版本判斷
2、直接呼叫setStatusBarColor

Activity activity = this;
int color=Color.parseColor("#008000");
//針對版本5.x以上的即LOLLIPOP以上的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    //非全螢幕修改狀態列顏色
    Window window = activity.getWindow();
    //FLAG_TRANSLUCENT_STATUS為狀態列型別:半透明效果
    //取消設定透明狀態列,使 ContentView 內容不再覆蓋狀態列
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //需要設定這個 flag 才能呼叫 setStatusBarColor 來設定狀態列顏色
    //FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS為狀態列型別:支援著色
   window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //設定狀態列顏色  setStatusBarColor要求21以上
    window.setStatusBarColor(color);
    ViewGroup contentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
    View childView = contentView.getChildAt(0);//對應activity佈局檔案根標籤
    if (childView != null) {
    //注意不是設定 ContentView 的 FitsSystemWindows, 而是設定 ContentView 的第一個子 View . 預留出系統 View 的空間.
        ViewCompat.setFitsSystemWindows(childView, true);
    }
}

執行效果:根據標題顏色著色

這裡寫圖片描述

android:fitsSystemWindows
setFitsSystemWindows()

所有實現 Translucent System Bar 效果的Activity,都需要在根佈局裡設定 android:fitsSystemWindows=”true” 。設定了該屬性的作用在於,不會讓系統導航欄和我們app的UI重疊,導致互動問題.以下給出效果圖說明該屬性。

這裡寫圖片描述

全螢幕:contentview延伸

程式碼位置:com.example.systembar.CodeFullActivity#onCreate

這裡寫圖片描述

//去掉titlebar-全屏模式
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
//細節supportRequestWindowFeature一定要在setContentView之前設定
setContentView(R.layout.activity_code_full);
Activity activity = this;
int statusColor = Color.parseColor("#008000");
//針對版本5.x以上的即LOLLIPOP以上的
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = activity.getWindow();
    //設定透明狀態列,這樣才能讓 ContentView 向上
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //需要設定這個 flag 才能呼叫 setStatusBarColor 來設定狀態列顏色
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //設定狀態列顏色
    window.setStatusBarColor(statusColor);
    ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
    View mChildView = mContentView.getChildAt(0);
    if (mChildView != null) {
        //注意不是設定 ContentView 的 FitsSystemWindows, 而是設定 ContentView 的第一個子 View .
        // 使其不為系統 View 預留空間.不預留空間的話 狀態列就會覆蓋佈局頂部
        ViewCompat.setFitsSystemWindows(mChildView, false);
    }
}

執行效果

這裡寫圖片描述

4.4以上,準備4.4模擬器

這裡寫圖片描述

5.x以上的實現方式不使4.4以上的生效.所以要考慮一下相容方案。

全螢幕:contentview延伸

思路:暫時儲存標題欄時可以清楚得看到只要將contentView延伸到statusbar下方.它與statusBar共同放在一個FrameLayout裡

這裡寫圖片描述

程式碼位置:com.example.systembar.CodeFullActivity#onCreate

1、獲取系統statusBar的高度

private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
public static int getStatusBarHeight(Context context) {
    int result = 0;
    //訪問android.jar內的dimen中包含的status_bar_height屬性值
    int resourceId = context.getResources().getIdentifier(STATUS_BAR_HEIGHT_RES_NAME, "dimen", "android");
    if (resourceId > 0) {
        result = context.getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

2、設定無標題欄

//去掉titlebar-全屏模式
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
//細節supportRequestWindowFeature一定要在setContentView之前設定
setContentView(R.layout.activity_code_full);

3、設定 contentView的marginTop上移狀態列高度

//KITKAT為4.4sdk的名稱
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window window = activity.getWindow();
    ViewGroup contentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
    //首先使 ChildView 不預留空間
    View childView = contentView.getChildAt(0);//layout file對應的根標籤
    if (childView != null) {
        //此時status會遮蓋contnetview
        ViewCompat.setFitsSystemWindows(childView, false);
    }
    int statusBarHeight = getStatusBarHeight(activity);
    //需要設定這個 flag 才能設定狀態列
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //避免多次呼叫該方法時,多次移除了 View
    if (childView != null && childView.getLayoutParams() != null && childView.getLayoutParams().height == statusBarHeight) {
        //移除假的 View.
        contentView.removeView(childView);
        childView = contentView.getChildAt(0);
    }
    if (childView != null) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) childView.getLayoutParams();
        //清除 ChildView 的 marginTop 屬性
        if (lp != null && lp.topMargin >= statusBarHeight) {
            //減少layout的topmargin 使用layout佈局的整體延伸到statusBar下方
            lp.topMargin -= statusBarHeight;
            childView.setLayoutParams(lp);
        }
    }
}

Deug下可以檢視到

這裡寫圖片描述

  • activity.findViewById(Window.ID_ANDROID_CONTENT);獲取的是存放layout的FrameLayout具體型別為ContentFrameLayout

  • Layout的內容可以從 contentView.getChildAt(0);獲取

  • 在狀態列透明的情況下 lp.topMargin -= statusBarHeight;可以使用layout上移

執行效果

這裡寫圖片描述

非全螢幕:Javacod著色狀態列

  • 獲取系統狀態列高度(同上)
  • 在狀態列透明情況下下移contnetView 距離為狀態列高度
  • 如果存在著色View則修改背景色
  • 如果不存在著色View則新增同時設定背景色
//判斷當前sdk是4.4  KITKAT為4.4sdk的名稱
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Window window = activity.getWindow();
        ViewGroup contentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
        //設定狀態列透明
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        //獲取狀態列高度
        int statusBarHeight = getStatusBarHeight(activity);
        //在全屏模式下 使用contentView內容下移狀態列高度
        View childView = contentView.getChildAt(0);
        if (childView != null) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) childView.getLayoutParams();
            //如果已經為 ChildView 設定過了 marginTop, 再次呼叫時直接跳過
            if (lp != null && lp.topMargin < statusBarHeight && lp.height != statusBarHeight) {
                //不預留系統空間
                ViewCompat.setFitsSystemWindows(childView, false);
                lp.topMargin += statusBarHeight;//在狀態列透明的情況下 contentView marginTop改為狀態列高度
                childView.setLayoutParams(lp);
            }
        }
       //下移的狀態列高度  已經存在著色View直接設定color
        View statusBarView = contentView.getChildAt(0);
        if (statusBarView != null && statusBarView.getLayoutParams() != null && statusBarView.getLayoutParams().height == statusBarHeight) {
            //避免重複呼叫時多次新增已經著色的View
            statusBarView.setBackgroundColor(statusColor);
        }else
        {
            //如果未存在剛新增著色View下次通過contentView.getChildAt(0);即為該著色View
            statusBarView = new View(activity);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
            statusBarView.setBackgroundColor(statusColor);
            //向 ContentView 中新增已經著色的View
            contentView.addView(statusBarView, 0, lp);
        }

    }
}

執行效果,我在此處新增的著色View背景為綠色
這裡寫圖片描述

此時還可以去掉系統自帶的標題欄

開源第三方SystemBarTint

4.4以上
這裡寫圖片描述

5.x以上
這裡寫圖片描述

在android5.0以上

<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/titleBlue</item>
        <item name="colorPrimaryDark">#3A5FCD</item>
        <item name="@android:textColorPrimary">@android:color/white</item>
    </style>

    <style name="AppTheme" parent="AppBaseTheme">
        <!-- 隱藏標題欄 -->
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@color/transparent</item>
        <!--<item name="colorControlNormal">@color/white</item>-->
    </style>

當statusBarColor設定為透明色後,狀態列的顏色為白色,如果佈局檔案加上屬性android:fitsSystemWindows=”true”後,狀態列則顯示colorPrimaryDark顏色

styles(4.0之前)

<!-- 半透明的主題樣式 -->
   <style name="NavigationTransparent" parent="AppTheme">
       <!-- Android 4.4 之前的版本跟隨系統預設的樣式-->
   </style>

styles(4.4之後)

<!-- 半透明的主題樣式 -->
   <style name="NavigationTransparent" parent="AppTheme">
       <!-- 狀態列 半透明 -->
       <item name="android:windowTranslucentStatus">true</item>
       <!-- 導航欄 半透明-->
       <item name="android:windowTranslucentNavigation">true</item>
   </style>

styles(5.0之後)

<!-- 半透明的主題樣式 -->
   <style name="NavigationTransparent" parent="AppTheme">
       <!-- 導航欄 半透明-->
       <item name="android:windowTranslucentNavigation">true</item>
       <!-- 狀態列 半透明 -->
       <item name="android:windowTranslucentStatus">true</item>
       <!-- Android 5.0開始需要把顏色設定為透明。否狀態列會用系統預設的淺灰色 (Android 5.0以後支援修改顏色,需指定顏色)-->
       <item name="android:statusBarColor">@android:color/transparent</item>
   </style>

相關推薦

Android沉浸應用

一、概念 首先讓我們看一下預設狀態列的顯示效果 以下以微信與qq為例: 由於Android 系統自4.2 開始 UI 上就沒多大改變,而4.4增加了透明狀態列與導航欄的功能如以下圖的效果。 從以上的圖可以看出Activity的content

Android 沉浸模式(支援API 19及以上系統)

Adnroid 4.4(API level 19)中引入為setSystemUiVisibility()引入了一個新標籤SYSTEM_UI_FLAG_IMMERSIVE,它可以讓應用進入真正的全屏模式。 而現在我實現的方式是通過Theme以及系統提供的控制元件

android沉浸狀態列下,各種鍵盤擋住輸入框解決辦法

*本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 在開發中,經常會遇到鍵盤擋住輸入框的情況,比如登入介面或註冊介面,彈出的軟鍵盤把登

android 使用沉浸模式

這個是我自己的看官方問的總結的程式碼 親身體現可以實現 在想呼叫的地方呼叫即可 這個程式碼片段隱藏了系統條 private void hideSystemUI() { View decorView = getWindow().ge

Android 模式

activity重新如下方法即可:   @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus

Android-淺談沉浸模式

背景 那是一個寒冷的季節,“沉浸式”這個詞悄然對映進我的腦海。看著它那高階大氣的樣式,頓時感覺自己眼前一亮,如此高階大氣的設計怎能不學,怎能不用呢? 作用 眾所周知,“沉浸式”是google在Android4.4推出的一種新模式,可以使APP最上方的顯示系統訊息的狀態列(Status Ba

android 去掉底部虛擬導航欄的方法

  @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { getWin

Android模式處理

if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { 2. // 透明狀態列 3. getWindow().addFlags( 4. WindowMan

Android進階----------沉浸標題欄實現的學習

1. 需注意只有5.0以上適用,以下需要適配處理,否則程式會崩掉。 一、values-v19/styles.xml 無效果,僅防止低版本崩掉 <resources> <!--values-v19。v19 開始有 android:windowTra

Android 橫豎+碎片的應用

最終效果展示: 專案介紹: 通過碎片的方式顯示標題列表和內容,其中也牽涉到橫豎屏的知識 專案程式碼下載:http://files.cnblogs.com/files/Laopengblog/%E7%A2%8E%E7%89%87and%E6%A8%AA%E7%AB%96%E5%B1%8F.rar 編寫

Android大坑之沉浸StatusBar+actionbar

在開發中,我們經常遇到, 想讓Statusbar透明,其中的效果相比大家也都知道, 但這裡面的坑太多了啊……. 今天就來總結一下他的各種方法. 1.Status的消失 因為狀態列是在4.4加入的,所以我們在Android4.4以下是沒有Statusbar

Qt Android 設定

寫在前面:本文解決的問題是Qt 編譯到 Android 上,實現全屏的辦法,同樣適用於qml 看了很多網上說的辦法,大多都是基於Qt 5.8 5.9的版本,都是說需要去重寫java的OnCreate()方法,哇,各種騷操作,然後我發現程式直接就崩潰了。 冥思苦想,按照下面的辦法成

Android 漸變色沉浸狀態列

效果圖在最下 在AndroidManifest.xml中的activity中使用自定義主題 <activity android:name=".dailyAccompany.view.activity.AlarmListActivity" android:theme="@style/M

Android 顯示

去掉標題欄 requestWindowFeature(Window.FEATURE_NO_TITLE); 去掉狀態列 getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,

android 切換到非 頁面抖動

解決辦法:    在全屏的activity finish之前手動退出全屏window.setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_

Android 方法(繼承AppCompatActivity;繼承Activity)

程式碼設定: 繼承Activity時設定為 this.requestWindowFeature( Window.FEATURE_NO_TITLE); 繼承AppCompatActivity用上面的

android 去掉底部虛擬導航欄

@Overridepublic void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);if (hasFocus) {getWindow().getDecorView

Android 但是有狀態列

全屏 但是有狀態列 private void hideStatusBar() { WindowManager.LayoutParams attrs = getWindow().getAttributes(); attrs.flags |= WindowMa

android問題(隱藏虛擬按鍵)

android4.0沒有真正的全屏顯示,控制面板隱藏不了,唯一能做的,就是將控制鍵改成三個小圓點。 具體的做大是在add layout之後,然後呼叫如下的程式碼: enterLightsOutMode(getWindow()); public static void en

Android實戰】沉浸狀態列實現(上)

傳統的手機狀態列是呈現出黑色條狀的,有的和手機主介面有很明顯的區別。這樣就在一定程度上犧牲了視覺寬度,介面面積變小。 沉浸模式的狀態列和主介面完全融為了一體,在設計上有不同的視覺感受。 我們先上兩張圖,很容易看出區別:        Android在4.4的時候增加了透