前言

国际惯例:先发一通牢骚,他大爷的&*¥%……&,别误会我不是骂产品的,我是痛诉Android的状态栏适配的
事情是这样的,文章详情界面需要透明状态栏,下面可以评论,需求效果图如下。
头部状态栏透明:

底部有输入框:

我想关于透明状态栏的实现不算难,网上一搜有很多文章都写过,我在这里提供一些参考链接:

  • Android开发:Translucent System Bar 的最佳实践
  • 透明状态栏(StatusBar)的全适配
  • Android状态栏合集-管你透不透明
  • Android-transulcent-status-bar
  • Android 透明状态栏实现方案

难点是:

  1. 如果布局中要用到软键盘,就必须加上android:fitsSystemWindows=”true”属性,否则键盘弹出时,adjustResize属性不起作用,这样就会导致软件盘覆盖输入框。但是当你加上android:fitsSystemWindows=”true”时会导致状态栏变成灰白色
  2. 华为手机,准确的说是Android原生的系统在你设置完透明状态栏后会是半透明,并不是透明

实现

踩坑步骤

先实现透明:

Window w = getWindow();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {    w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE|View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);    w.setStatusBarColor(Color.TRANSPARENT);}

效果如下

但是设置android:fitsSystemWindows=”true”后效果是这样

这样的效果肯定不是我们想要的效果,后来我尝试了不使用android:fitsSystemWindows=”true”,自己监听布局变化,代码将输入框顶起到软件盘上面,下面是代码可以了解一下,但是这样写有深坑,就是华为手机还有Google原生系统有一个东西叫做NavigationBar,就是下面这个。这个东西会影响我的计算,总之自己计算就不是个明智的选择

    /**     * 动态调整布局,使软件盘弹出时输入框弹出到软件盘上面     */    private void adjustKeyboard() {        //初始化控件        rootLayout = (RelativeLayout) findViewById(R.id.root_layout);        final View v_push = findViewById(R.id.v_push);        //创建一个矩形, 用于获取输入法高度        final Rect r = new Rect();        //获取屏幕根View        final View decorView = this.getWindow().getDecorView();        //获取顶起ScrollView用的控件的布局参数, 我们是用LinearLayout包裹的所以注意来兴是LinearLayout的LayoutParams        final RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v_push.getLayoutParams();        //获取布局根View的ViewTree观察器, 监听布局变化        rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {            //当布局改变时, 会调用本方法            @Override            public void onGlobalLayout() {                //判断键盘显隐状态                decorView.getWindowVisibleDisplayFrame(r);                int screenHeight = rootLayout.getRootView().getHeight();                int keyboardHeight = screenHeight - r.bottom;                if (currentKeyboardHeight != keyboardHeight) {                    // 当键盘状态不一致时, 再改变布局                    layoutParams.height = keyboardHeight;                    v_push.setLayoutParams(layoutParams);                    //将键盘高度保存                    currentKeyboardHeight = keyboardHeight;                }            }        });    }

后来在stackoverflow搜索到了这个坑相关的问题如:

windowSoftInputMode=“adjustResize” not working with translucent action/navbar
Android How to adjust layout in Full Screen Mode when softkeyboard is visible
我采取了其中一种方案自定义FrameLayout作为界面的根布局解决上面那一块灰白色的东东

/** * @author Kevin * Date Created: 3/7/14 * * https://code.google.com/p/android/issues/detail?id=63777 *  * When using a translucent status bar on API 19+, the window will not * resize to make room for input methods (i.e. * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are * ignored). *  * To work around this; override {@link #fitSystemWindows(android.graphics.Rect)}, * capture and override the system insets, and then call through to FrameLayout's * implementation. *  * For reasons yet unknown, modifying the bottom inset causes this workaround to * fail. Modifying the top, left, and right insets works as expected. */public final class CustomInsetsFrameLayout extends FrameLayout {    private int[] mInsets = new int[4];    public CustomInsetsFrameLayout(Context context) {        super(context);    }    public CustomInsetsFrameLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    public CustomInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public final int[] getInsets() {        return mInsets;    }    @Override    protected final boolean fitSystemWindows(Rect insets) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {            // Intentionally do not modify the bottom inset. For some reason,            // if the bottom inset is modified, window resizing stops working.            // TODO: Figure out why.            mInsets[0] = insets.left;            mInsets[1] = insets.top;            mInsets[2] = insets.right;            insets.left = 0;            insets.top = 0;            insets.right = 0;        }        return super.fitSystemWindows(insets);    }    @Override    public final WindowInsets onApplyWindowInsets(WindowInsets insets) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {            mInsets[0] = insets.getSystemWindowInsetLeft();            mInsets[1] = insets.getSystemWindowInsetTop();            mInsets[2] = insets.getSystemWindowInsetRight();            return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,                    insets.getSystemWindowInsetBottom()));        } else {            return insets;        }    }}

效果如下:

你会看到,这样写确实灰白色statusbar没了,但是还是出了幺蛾子,titleBar被压在了状态栏下面,显然这也不是我们想要的效果,没有看到想要的效果先不要骂娘,你会发现我们距离成功之后一个statusBar的高度,好吧,这还不好办给他来个padding不就行了对就这么干。最终:

    private void initTitleBar() {        titleBarLayout= (FrameLayout) findViewById(R.id.title_bar_layout);        int statusBarHeight = getStatusBarHeight();        Window w = getWindow();        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE|View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);                w.setStatusBarColor(Color.TRANSPARENT);            }else{                w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);            }            //改变titlebar的高度            ViewGroup.LayoutParams lp = titleBarLayout.getLayoutParams();            lp.height += statusBarHeight;            titleBarLayout.setLayoutParams(lp);            //设置paddingtop            titleBarLayout.setPaddingRelative(0, statusBarHeight, 0, 0);        }    }    //获取statusbar高度    public int getStatusBarHeight() {        int result = 0;        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");        if (resourceId > 0) {            result = getResources().getDimensionPixelSize(resourceId);        }        return result;    }

效果:

总结

上面的方案只是解决方案的一种,具体问题说不定具体解决,如果你之后一个界面需要这样,你可以直接按照这种方式写,如果多个界面建议封装起来写在BaseActivitiy里面

有时候你会遇到半透明的情况效果如下:

可以加一句代码w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);在下面代码的前面

w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE|View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);            w.setStatusBarColor(Color.TRANSPARENT);

参考链接

  • http://stackoverflow.com/questions/21092888/windowsoftinputmode-adjustresize-not-working-with-translucent-action-navbar

更多相关文章

  1. 模仿iOS版微信的滑动View效果
  2. Android实现加载富文本以及SpannableString、SpannableStringBui
  3. Android(安卓)View的测量、布局、绘制过程详解(上)
  4. android 定制 View派生类
  5. Android中实现程序前后台切换效果。
  6. android 你或许不知道的屏幕适配
  7. Android(安卓)Layout 之 RelativeLayout RelativeLayout.LayoutP
  8. 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用
  9. 关于android UI布局自适应

随机推荐

  1. [android]EditText的一些设置
  2. 【安卓学习之开发工具】 Android(安卓)St
  3. Android开发实战-项目学习笔记(2)
  4. Android开发实例大全
  5. Android有用代码片段(四)
  6. Android(安卓)打包
  7. 【Android布局】在程序中设置android:gra
  8. Android(安卓)TextView内容过长加省略号,
  9. 【Android布局】在程序中设置android:gra
  10. Android系统自带样式(android:theme)解析