android 透明状态栏方法及其适配键盘上推(二)

在上一篇文章中介绍了一种设置透明状态栏及其适配键盘上推得方法。但是上一篇介绍的方法中有个缺点,就是不能消除掉statusbar的阴影。很多手机如(三星,Nexus都带有阴影)。即使我用了:

<android.support.design.widget.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       app:elevation="0dp"
       android:background="@android:color/transparent"
       android:theme="@style/AppTheme.AppBarOverlay">

       <android.support.v7.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           android:background="@android:color/transparent"
           app:popupTheme="@style/AppTheme.PopupOverlay" />
           
</android.support.design.widget.AppBarLayout>

  还是不能消除阴影。那怎么办呢?这里介绍一种我觉得还不错的方法,思路是:不用toolbar,直接通过代码设置界面为透明statusbar,在每个界面里增加一个statusbar高度的view用来适配界面的显示,否则界面最顶端会有部分被statusbar覆盖。

方法如下:

1. 修改您应用里每个界面里的最顶端的布局:

    <RelativeLayout
        android:id="@+id/total_tile_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:id="@+id/actionbar_tile_bg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </RelativeLayout>

       <!--titlebar的其他布局-->
</RelativeLayout>

2. 在activity的onCreate方法中(最好写在baseActivity里),增加如下代码,设置为透明statusbar同时清除背景阴影。

   

            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏
            // 状态栏字体设置为深色,SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 为SDK23增加
            getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

//            // 部分机型的statusbar会有半透明的黑色背景
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().setStatusBarColor(Color.TRANSPARENT);// SDK21

  

3.同时在activity的onCreate方法中(最好写在baseActivity里),调用initMarginTopWithStatusBarHeight方法

 

/**
     * 设置view的margintop高度为statusbar高度
     * @param view 就是上面的 actionbar_tile_bg 这个view
     * @param context
     */
public static void initMarginTopWithStatusBarHeight(View view,Context context){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null){
            view.setVisibility(View.VISIBLE);
            RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(view.getLayoutParams());
            rl.topMargin = getStatusBarHeight(context);
            view.setLayoutParams(rl);
        }else{
            view.setVisibility(View.GONE);
        }
    }

 

这样就可以实现6.0以上的机型statusbar为透明且没有阴影(6.0以下的没有测试过,我这个应用的需求就是要求6.0以上,有兴趣的同学可以去测试下)。

但是这样设置后,用上一篇的适配键盘上推或是虚拟按键的显示和隐藏适配就不行了,需要重新设置。

增加一个util类:

 

public class AndroidBug5497Workaround {

    // For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (final Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(final Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
            mChildOfContent = content.getChildAt(0);
            mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                public void onGlobalLayout() {
                    possiblyResizeChildOfContent(activity);
                }
            });
            frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
        }

    }

    private void possiblyResizeChildOfContent(Activity activity) {
        int usableHeightNow = computeUsableHeight();

        if (usableHeightNow != usableHeightPrevious) {

            int resourceId = activity.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
            //获取NavigationBar的高度
            int navigateHeight = activity.getResources().getDimensionPixelSize(resourceId);
            boolean hasSoftNavigateBar = navigationBarExist2(activity);
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4) || hasSoftNavigateBar) {
                if (heightDifference == 0){
                    heightDifference = navigateHeight;
                }
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return r.bottom;
    }


    /**
     * 判断是否虚拟按键,这个方法最管用
     * @param activity
     * @return
     */
    private boolean navigationBarExist2(Activity activity) {
        WindowManager windowManager = activity.getWindowManager();
        Display d = windowManager.getDefaultDisplay();

        DisplayMetrics realDisplayMetrics = new DisplayMetrics();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            d.getRealMetrics(realDisplayMetrics);
        }

        int realHeight = realDisplayMetrics.heightPixels;
        int realWidth = realDisplayMetrics.widthPixels;

        DisplayMetrics displayMetrics = new DisplayMetrics();
        d.getMetrics(displayMetrics);

        int displayHeight = displayMetrics.heightPixels;
        int displayWidth = displayMetrics.widthPixels;

        return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
    }

}

  在activity里onCreate里调用:

        AndroidBug5497Workaround.assistActivity(this);

  

OK,这两篇是我在开发过程中遇到的问题,记录并分享。


    

  

posted @ 2016-09-04 11:44  shaotine  阅读(1590)  评论(0编辑  收藏  举报