1. 程式人生 > >沉浸式的封裝(狀態列和底部導航同時實現)

沉浸式的封裝(狀態列和底部導航同時實現)

我在使用沉浸式的時候遇到很多坑,最典型的就是相容性問題,有的效果5.0以上很容易實現,但在4.4使用同樣的方法就不可取了,有的機型底部有虛擬導航按鈕,有的卻沒有,所有我們不僅要區分手機的版本,也要區分底部是否有導航欄。只有在4.4及以上才有沉浸式這麼一說的,在本次封裝中,我們要同時實現頂部狀態列和底部導航欄的沉浸式,需要的童鞋可以當做工具類,直接copy到自己的BaseActivity中進行使用。

之前寫過實現沉浸式方法的文章,詳情見http://blog.csdn.net/sinat_35159441/article/details/76839484 ,首先我們來分析一下,不是所有的Activity都需要實現沉浸式,所以設定沉浸式的方法沒必要做成抽象的,需要使用的Activity重寫一下即可。該方法實現步驟如下:

  • 如果當前版本為4.4,我們首先設定狀態列和導航欄透明,5.0不用
 //判斷手機的版本,如果是4.4的版本,則設定狀態列和導航欄透明,5.0以上不用設定,已經實現
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG
_TRANSLUCENT_STATUS); getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); }

在佈局里加入這裡寫圖片描述
* 判斷版本,4.4以下可以忽略,4.4使用反射機制動態設定Toolbar的高度,再設定其顏色,同樣使用反射設定導航欄的高度,再設定其顏色,5.0以上直接使用官方提供的API設定其顏色,高度使用預設的。

    /**
     * 設定頂部及底部的沉浸式,這個方法需要子類來調,必須在setContentView()之後呼叫
     */
public void setTranslucentBar(final Toolbar toolbar, final View navigationView, int barColor) { //當手機的版本在4.4的時候,設定透明之後,再設定高度,然後再設定顯示的顏色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (toolbar != null) { toolbar.post(new Runnable() { @Override public void run() { ViewGroup.LayoutParams layoutParams = toolbar.getLayoutParams(); layoutParams.height += getBarHeight("status_bar_height"); toolbar.setLayoutParams(layoutParams); } }); toolbar.setBackgroundColor(barColor); } if (navigationView != null) { //這時還要判斷當前手機有沒有底部虛擬導航欄,如果沒有的話,我們不做處理 if (hasNavigationView(getWindowManager())) { navigationView.post(new Runnable() { @Override public void run() { ViewGroup.LayoutParams layoutParams = navigationView.getLayoutParams(); layoutParams.height += getBarHeight("navigation_bar_height"); navigationView.setLayoutParams(layoutParams); } }); navigationView.setBackgroundColor(barColor); } } //5.0及以上 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().setStatusBarColor(barColor); getWindow().setNavigationBarColor(barColor); toolbar.setBackgroundColor(barColor); } else { //4.4以下,沒有沉浸式這一說,我們不做任何處理 } }

最終我的基類的程式碼如下:

/**
 * 實現頂部及底部沉浸式導航欄的基類
 */
public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //判斷手機的版本,如果是4.4的版本,則設定狀態列和導航欄透明,5.0以上不用設定,已經實現
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }

    /**
     * 設定頂部及底部的沉浸式,這個方法需要子類來調,必須在setContentView()之後呼叫
     */
    public void setTranslucentBar(final Toolbar toolbar, final View navigationView, int barColor) {
        //當手機的版本在4.4的時候,設定透明之後,再設定高度,然後再設定顯示的顏色
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            if (toolbar != null) {
                toolbar.post(new Runnable() {
                    @Override
                    public void run() {
                        ViewGroup.LayoutParams layoutParams = toolbar.getLayoutParams();
                        layoutParams.height += getBarHeight("status_bar_height");
                        toolbar.setLayoutParams(layoutParams);
                    }
                });

                toolbar.setBackgroundColor(barColor);
            }
            if (navigationView != null) {
                //這時還要判斷當前手機有沒有底部虛擬導航欄,如果沒有的話,我們不做處理
                if (hasNavigationView(getWindowManager())) {
                    navigationView.post(new Runnable() {
                        @Override
                        public void run() {
                            ViewGroup.LayoutParams layoutParams = navigationView.getLayoutParams();
                            layoutParams.height += getBarHeight("navigation_bar_height");
                            navigationView.setLayoutParams(layoutParams);
                        }
                    });
                    navigationView.setBackgroundColor(barColor);
                }
            }
            //5.0及以上
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().setStatusBarColor(barColor);
            getWindow().setNavigationBarColor(barColor);
            toolbar.setBackgroundColor(barColor);
        } else {
            //4.4以下,沒有沉浸式這一說,我們不做任何處理
        }
    }

    /**
     * 判斷當前手機是否含有底部導航欄,如果沒有的話返回false,有的話返回true
     *
     * @return
     */
    private boolean hasNavigationView(WindowManager wm) {
        Display display = wm.getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getRealMetrics(outMetrics);
        //獲取螢幕實際的高度,實際的高度包括內容的高度和底部導航的高度
        int realHeight = outMetrics.heightPixels;

        outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        //螢幕中內容的高度
        int heightPixels = outMetrics.heightPixels;
        //如果實際的高度和大於內容的高度說明該手機含有底部導航,否則沒有
        return realHeight - heightPixels > 0;
    }

    /**
     * 獲取狀態列或是底部導航欄的高度
     *
     * @return
     */
    public int getBarHeight(String dimenName) {
        int height = 0;
        try {
            Class clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            String s = clazz.getField(dimenName).get(object).toString();
            int heightId = Integer.parseInt(s);
            //dp 2 px
            height = getResources().getDimensionPixelSize(heightId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return height;
    }
}

它的子類的程式碼如下:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        navigationView = findViewById(R.id.navi);
        setTranslucentBar(toolbar, navigationView, getResources().getColor(R.color.barcolor));
    }

最終效果如下:
這裡寫圖片描述