Android 沉浸式設(shè)計Translucent

什么是沉浸式

官方的沉浸式Translucent:就是讓整個APP沉浸(充斥了整個屏幕)在屏幕里面,沒有顯示狀態(tài)欄,甚至沒有顯示底部導(dǎo)航欄。
平時大家所討論的沉浸式:比如QQ的頂部Toolbar和狀態(tài)欄程一體的顏色。

兼容開發(fā):

  1. 5.0+ API
    5.0+自動實現(xiàn)了沉浸式效果,狀態(tài)欄的顏色跟隨你的主題里面的colorPrimaryDark屬性。

    1)通過設(shè)置主題達(dá)到

    <style name="AppTheme" parent="AppBaseTheme">

    <item name="android:textColor">@color/mytextcolor</item>
    <item name="colorPrimary">@color/colorPrimary_pink</item>
    <item name="colorPrimaryDark">@color/colorPrimary_pinkDark</item>


    </style>
    2)通過設(shè)置樣式屬性解決
    <item name="android:statusBarColor">@color/system_bottom_nav_color</item>
    3)通過代碼設(shè)置
    //5.0+可以直接用API來修改狀態(tài)欄的顏色。
    getWindow().setStatusBarColor(getResources().getColor(R.color.material_blue_grey_800));

  2. 4.4 API
    (低于4.4API,不可以做到)
    用到一些特殊手段!----4.4(KitKat)新出的API,可以設(shè)置狀態(tài)欄為透明的。
    1.在屬性樣式里面解決(不推薦使用,因為兼容不好)
    <item name="android:windowTranslucentStatus">true</item>
    2.再代碼里面解決
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    setContentView(R.layout.activity_main);
    出現(xiàn)副作用:
    APP的內(nèi)容頂?shù)阶钌厦嫒チ耍礌顟B(tài)欄會遮擋一部分界面。很坑
    解決辦法(有幾種):
    1)給Toolbar設(shè)置android:fitsSystemWindows="true"
    該屬性的作用:設(shè)置布局時,是否考慮當(dāng)前系統(tǒng)窗口的布局,如果為true就會調(diào)整整個系統(tǒng)窗口
    布局(包括狀態(tài)欄的view)以適應(yīng)你的布局。

但是:又出現(xiàn)了一個bug,當(dāng)里面有ScrollView并且ScrollView里面有Edittext的時候,就會出現(xiàn)軟鍵盤一彈起就會把toolbar拉下來,很難看
這種辦法有什么價值呢?如果里面沒有ScrollView就可以用。
2)推薦
靈感:發(fā)現(xiàn)給布局最外層容器設(shè)置android:fitsSystemWindows="true" 可以達(dá)到狀態(tài)欄透明,并且露出底色---android:windowBackground顏色。
巧妙地解決:步驟:
1.在最外層容器設(shè)置android:fitsSystemWindows="true"
2.直接將最外層容器(也可以修改-android:windowBackground顏色)設(shè)置成狀態(tài)欄想要的顏色
3.下面剩下的布局再包裹一層正常的背景顏色。

3)修改Toolbar的高度
1.設(shè)置狀態(tài)欄的透明屬性,不要給Toolbar設(shè)置android:fitsSystemWindows="true"
2.需要知道狀態(tài)欄的高度是多少?去源碼里面找找

<dimen name="status_bar_height">24dp</dimen>

<dimen name="navigation_bar_height">48dp</dimen>
反射手機(jī)運行的類:android.R.dimen.status_bar_height.

3.修改Toolbar的PaddingTop(因為純粹增加toolbar的高度會遮擋toobar里面的一些內(nèi)容)
toolbar.setPadding(
toolbar.getPaddingLeft(),
toolbar.getPaddingTop()+getStatusBarHeight(this),
toolbar.getPaddingRight(),
toolbar.getPaddingBottom());

    private int getStatusBarHeight(Context context) {
        // 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
        int statusHeight = -1;
        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;
    }

NavigationBar沉浸式效果

  1. 5.x 底部虛擬導(dǎo)航沉浸效果
    1)屬性解決
    navigationBarColor
    2)代碼
    getWindow().setNavigationBarColor()
  1. 4.4
    用到一些特殊手段!----4.4(KitKat)新出的API,可以設(shè)置虛擬導(dǎo)航欄為透明的。
    步驟:
    1)在布局底部添加一個高度為0.1dp的view
    2)動態(tài)設(shè)置底部View的高度為虛擬導(dǎo)航欄的高度
    View nav = findViewById(R.id.nav);
    LayoutParams p = nav.getLayoutParams();
    p.height += getNavigationBarHeight(this);
    nav.setLayoutParams(p);
    3.做兼容性判斷
    1)SDK版本不一樣
    兩個區(qū)間:1. 大于5.0;2.=<4.4sdk<5.0

    2)有的沒有虛擬導(dǎo)航欄
    判斷是否有虛擬導(dǎo)航欄(源碼里面有方法可以得到是否有虛擬導(dǎo)航,反射得到)

    3)有的有虛擬導(dǎo)航,但是還可以開關(guān)
    判斷是否虛擬導(dǎo)航欄打開了

一步解決2)3)兩個問題: NavigationBarHeight=整個屏幕的高度 - 內(nèi)容部分view的高度 判斷是否>0

代碼:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class BaseTranslucentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        //判斷版本,如果[4.4,5.0)就設(shè)置狀態(tài)欄和導(dǎo)航欄為透明
        if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
                &&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //設(shè)置虛擬導(dǎo)航欄為透明
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }
    
    @SuppressLint("NewApi")
    public void setOrChangeTranslucentColor(Toolbar toolbar,View bottomNavigationBar, int translucentPrimaryColor){
        //判斷版本,如果[4.4,5.0)就設(shè)置狀態(tài)欄和導(dǎo)航欄為透明
        if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
                &&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
            if(toolbar!=null){
                //1.先設(shè)置toolbar的高度
                LayoutParams params = toolbar.getLayoutParams();
                int statusBarHeight = getStatusBarHeight(this);
                params.height += statusBarHeight ;
                toolbar.setLayoutParams(params );
                //2.設(shè)置paddingTop,以達(dá)到狀態(tài)欄不遮擋toolbar的內(nèi)容。
                toolbar.setPadding(
                        toolbar.getPaddingLeft(),
                        toolbar.getPaddingTop()+getStatusBarHeight(this), 
                        toolbar.getPaddingRight(),
                        toolbar.getPaddingBottom());
                //設(shè)置頂部的顏色
                toolbar.setBackgroundColor(translucentPrimaryColor);
            }
            if(bottomNavigationBar!=null){
                //解決低版本4.4+的虛擬導(dǎo)航欄的
                if(hasNavigationBarShow(getWindowManager())){
                    LayoutParams p = bottomNavigationBar.getLayoutParams();
                    p.height += getNavigationBarHeight(this);
                    bottomNavigationBar.setLayoutParams(p);
                    //設(shè)置底部導(dǎo)航欄的顏色
                    bottomNavigationBar.setBackgroundColor(translucentPrimaryColor);
                }
            }
        }else if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.LOLLIPOP){
            getWindow().setNavigationBarColor(translucentPrimaryColor);
            getWindow().setStatusBarColor(translucentPrimaryColor);
        }else{
            //<4.4的,不做處理
        }
    }
    

    private int getNavigationBarHeight(Context context) {
        return getSystemComponentDimen(this, "navigation_bar_height");
    }

    /**
     * 獲取狀態(tài)欄的高度
     * @param context
     * @return
     */
    private int getStatusBarHeight(Context context) {
        // 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
        return getSystemComponentDimen(this, "status_bar_height");
    }
    
    private static int getSystemComponentDimen(Context context, String dimenName){
        // 反射手機(jī)運行的類:android.R.dimen.status_bar_height.
        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            String heightStr = clazz.getField(dimenName).get(object).toString();
            int height = Integer.parseInt(heightStr);
            //dp--->px
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }
    
    private static boolean hasNavigationBarShow(WindowManager wm){
        Display display = wm.getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        //獲取整個屏幕的高度
        display.getRealMetrics(outMetrics);
        int heightPixels = outMetrics.heightPixels;
        int widthPixels = outMetrics.widthPixels;
        //獲取內(nèi)容展示部分的高度
        outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        int heightPixels2 = outMetrics.heightPixels;
        int widthPixels2 = outMetrics.widthPixels;
        int w = widthPixels-widthPixels2;
        int h = heightPixels-heightPixels2;
        System.out.println("~~~~~~~~~~~~~~~~h:"+h);
        return  w>0||h>0;//豎屏和橫屏兩種情況。
    }
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容