laobie / StatusBarUtil

A util for setting status bar style on Android App.
http://t.cn/Rq746Kb
Apache License 2.0
8.81k stars 1.72k forks source link

小米手机 4.4 版本 StatusBarUtil.setColor 方法和 StatusBarUtil.setTransparentForImageViewInFragment 方法切换调用会停止运行。 #52

Closed Jimmy-J closed 1 year ago

Jimmy-J commented 8 years ago

如题,当我这个View快速向下滑动会出现异常 如果慢慢往下滑则不会 请猴子大神帮忙看看

scrollableLayout.setOnScrollListener(new ScrollableLayout.OnScrollListener() {
            @Override
            public void onScroll(int currentY, int maxY) {
                if (currentY > mHeight / 1.5) {
                    if (isTransparent) {
                        isTransparent = false;
                        StatusBarUtil.setColor(activity, ContextCompat.getColor(activity, R.color.common_red));
                        rlTitleBar.setBackgroundColor(ContextCompat.getColor(activity, R.color.common_red));
                    }
                } else {
                    if (!isTransparent) {
                        isTransparent = true;
                        StatusBarUtil.setTransparentForImageViewInFragment(activity, null);
                        rlTitleBar.setBackgroundColor(ContextCompat.getColor(activity, R.color.transparent));
                    }
                }
            }
        });

异常信息:

          java.lang.NullPointerException
                                                                at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3072)
                                                                at android.view.View.getDisplayList(View.java:13311)
                                                                at android.view.View.getDisplayList(View.java:13415)
                                                                at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1570)
                                                                at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1449)
                                                                at android.view.ViewRootImpl.draw(ViewRootImpl.java:2427)
                                                                at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2299)
                                                                at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1929)
                                                                at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1046)
                                                                at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5655)
                                                                at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
                                                                at android.view.Choreographer.doCallbacks(Choreographer.java:574)
                                                                at android.view.Choreographer.doFrame(Choreographer.java:544)
                                                                at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
                                                                at android.os.Handler.handleCallback(Handler.java:733)
                                                                at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                at android.os.Looper.loop(Looper.java:136)
                                                                at android.app.ActivityThread.main(ActivityThread.java:5052)
                                                                at java.lang.reflect.Method.invokeNative(Native Method)
                                                                at java.lang.reflect.Method.invoke(Method.java:515)
                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
                                                                at dalvik.system.NativeStart.main(Native Method)
laobie commented 8 years ago

看报错信息不像是设置状态栏导致的问题呢,你找到具体出错的地方了么

Jimmy-J commented 8 years ago

我用debug跟踪了一下 decorView.removeViewAt(count - 1); 执行完这一行代码后会有异常 如果不remove 而是设置为GONE的话则不会有异常了

@TargetApi(Build.VERSION_CODES.KITKAT)
    private static void clearPreviousSetting(Activity activity) {
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int count = decorView.getChildCount();
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
//            decorView.removeViewAt(count - 1);
            View view = decorView.getChildAt(count - 1);
            view.setVisibility(View.GONE);
            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setPadding(0, 0, 0, 0);
        }
    }
Jimmy-J commented 8 years ago

@laobie 现在我在 setColor里面判断如果StatusBarView 为GENO的话那我先移除然后在进行重新添加,简单的测试了一下正常使用是没有问题的,,猴哥你看一下会不会有什么其它影响

 public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            int count = decorView.getChildCount();
            View view = decorView.getChildAt(count - 1);
            if (count > 0 && view instanceof StatusBarView) {
                if (view.getVisibility() != View.GONE){
                    decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
                }else {
                    decorView.removeView(view);
                    StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
                    decorView.addView(statusView);
                }
            } else {
                StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
                decorView.addView(statusView);
            }
            setRootView(activity);
        }
    }
laobie commented 8 years ago

@Jimmy-J clearPreviousSetting 这个方法有问题吧 setColor() 方法处理应该没问题的

laobie commented 8 years ago

@Jimmy-J 你的界面是用 fragment 来做的么

Jimmy-J commented 8 years ago

@laobie 是的界面是使用的 fragment 来做的,要实现的效果就是类似手机 qq 空间那种,需要全屏图片展示和有导航栏展示两种互换

Jimmy-J commented 8 years ago

@laobie 是的 我跟了一下 clearPreviousSetting() 这个方法 decorView.removeViewAt(count - 1) 执行过这句后就会抛出一个空指针,现在猜想会不会是哪个 ViewGroup 去获取它的时候 它已经被移除了导致的,不过还没什么收获。现在暂时在clearPreviousSetting()里面先GONE 然后放到setColor里面去remove了

laobie commented 8 years ago

@Jimmy-J 确实有点奇怪,你要能将你这做成一个 demo 的话,我可以测试下= =

Jimmy-J commented 8 years ago

@laobie 我把demo发到 chjie.jaeger@gmail.com 你这个邮箱了,你有时间的话帮忙看看 非常感谢

laobie commented 8 years ago

@Jimmy-J 好的

jeonhei commented 7 years ago

确实会这样 在fragment里先调用setColor()然后再调用setTransparentForImageViewInFragment()就会崩溃 我是这样解决的: handler.post(new Runnable() { @Override public void run() { StatusBarUtil.setTransparentForImageViewInFragment(); } }); 把方法调用同步到UI线程里 不用改动源代码即可避免crash 而且目前运作良好

jingchao920315 commented 6 years ago

setColorNoTranslucent 和setDarkMode 一起使用在4.4.0 、4.4.1、4.4.2 都会报NullPointerException , Process: com.luojilab.player, PID: 16636 java.lang.NullPointerException at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2952) at android.view.View.draw(View.java:14529) at android.widget.FrameLayout.draw(FrameLayout.java:472) at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2518) at android.view.View.getDisplayList(View.java:13423) at android.view.View.getDisplayList(View.java:13465) at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1570) at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1449) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2662) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2529) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2158) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1227) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6256) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) at android.view.Choreographer.doCallbacks(Choreographer.java:574) at android.view.Choreographer.doFrame(Choreographer.java:544) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5110) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:702) at dalvik.system.NativeStart.main(Native Method)

@laobie 有什么解决方案了吗??