Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

marginInfo 未设置时,addHighLight 未添加进去,导致显示时 crash #80

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

wdeo3601
Copy link

报错日志如下:

Process Name: 'com.wln100.future.debug'
Thread Name: 'main'
Back traces starts.
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference
	at zhy.com.highlight.view.HightLightView.buildTipLayoutParams(HightLightView.java:251)
	at zhy.com.highlight.view.HightLightView.updateTipPos(HightLightView.java:231)
	at zhy.com.highlight.view.HightLightView.onLayout(HightLightView.java:220)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.widget.FrameLayout.layoutChildren(FrameLayout.java:334)
	at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1857)
	at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1701)
	at android.widget.LinearLayout.onLayout(LinearLayout.java:1610)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.widget.FrameLayout.layoutChildren(FrameLayout.java:334)
	at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1857)
	at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1701)
	at android.widget.LinearLayout.onLayout(LinearLayout.java:1610)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at com.huawei.internal.widget.HwFreeFormCaptionView.onLayout(HwFreeFormCaptionView.java:859)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.widget.FrameLayout.layoutChildren(FrameLayout.java:334)
	at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
	at com.android.internal.policy.DecorView.onLayout(DecorView.java:1144)
	at android.view.View.layout(View.java:22491)
	at android.view.ViewGroup.layout(ViewGroup.java:6528)
	at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3743)
	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3207)
	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2166)
	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8884)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1280)
	at android.view.Choreographer.doCallbacks(Choreographer.java:1019)
	at android.view.Choreographer.doFrame(Choreographer.java:911)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1248)
	at android.os.Handler.handleCallback(Handler.java:900)
	at android.os.Handler.dispatchMessage(Handler.java:103)
	at android.os.Looper.loop(Looper.java:219)
	at android.app.ActivityThread.main(ActivityThread.java:8668)
	at java.lang.reflect.Method.invoke(Method.java)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
Back traces ends.

我的高亮提示场景是不需要给高亮 View 扣矩形,且提示 View 需要在屏幕的顶部,添加高亮提示 View 的代码如下:

addHighLight(
            targetView,
            decorLayoutId,
            object : OnBottomPosCallback() {
                override fun getPosition(
                    rightMargin: Float,
                    bottomMargin: Float,
                    rectF: RectF?,
                    marginInfo: MarginInfo?,
                ) {
                    marginInfo?.rightMargin = 0f
                    marginInfo?.topMargin = rectF?.top
                }
            },
            object : RectLightShape() {
                override fun resetRectF4Shape(viewPosInfoRectF: RectF, dx: Float, dy: Float) {
                    viewPosInfoRectF.setEmpty()
                }
            }
        )

marginInfo 只设置了 top 的值,正常情况下,top 的值是状态栏的高度,此时 marginInfo 里是有值的,高亮 View 可以正常显示;当使用鸿蒙平板的小窗模式后,因为小窗脱离状态栏了,所以 top 值就成 0 了,此时 marginInfo 里的值都为 0,在调用 HighLight.show() 后,之后的调用链会走到 HighLightView.addViewForEveryTip(),这个方法中因为 marginInfo 都是 0,所以这里 LayoutParams 会返回 null,直接 return 了,没添加上高亮布局,导致现实的时候 crash 了:

    //HighLight .java
    @Override
    public HighLight show() {
        ...
        //延迟添加提示布局
        hightLightView.addViewForTip();
        ...
        return this;
    }

   //HighLightView.java
    public void addViewForTip()
    {
        if (isNext)
        {
           ...
            mViewPosInfo = mViewRects.get(mPosition);
            //移除所有tip再添加当前位置的tip布局
            removeAllTips();
            addViewForEveryTip(mViewPosInfo);
           ...
        } else
        {
            ...
        }
    }

    //HighLightView.java
    private void addViewForEveryTip(HighLight.ViewPosInfo viewPosInfo)
    {
        View view = mInflater.inflate(viewPosInfo.layoutId, this, false);
        ...
        LayoutParams lp = buildTipLayoutParams(view, viewPosInfo);
        if (lp == null) return;  //这里直接返回了,没有添加 View,导致 crash
        ...
        addView(view, lp);
    }

    //HighLightView.java
    private LayoutParams buildTipLayoutParams(View view, HighLight.ViewPosInfo viewPosInfo)
    {
        LayoutParams lp = (LayoutParams) view.getLayoutParams();
        if (lp.leftMargin == (int) viewPosInfo.marginInfo.leftMargin &&
                lp.topMargin == (int) viewPosInfo.marginInfo.topMargin &&
                lp.rightMargin == (int) viewPosInfo.marginInfo.rightMargin &&
                lp.bottomMargin == (int) viewPosInfo.marginInfo.bottomMargin) return null; //因为 marginInfo 都是 0,走到这个条件中返回了 null

        ...
        return lp;
    }

以上调用链,注释中解释了 crash 的原因。
我的解决方案是,在 addViewForEveryTip 中,不再调用 buildTipLayoutParams 方法,去掉 null 的判断,直接把 marginInfo 的值赋给 LayoutParams,保证 addView 可以调用到:

    //HighLightView.java
    private void addViewForEveryTip(HighLight.ViewPosInfo viewPosInfo)
    {
        View view = mInflater.inflate(viewPosInfo.layoutId, this, false);
        //设置id为layout id 供HighLight查找
        view.setId(viewPosInfo.layoutId);

        LayoutParams lp = (LayoutParams) view.getLayoutParams();

        lp.leftMargin = (int) viewPosInfo.marginInfo.leftMargin;
        lp.topMargin = (int) viewPosInfo.marginInfo.topMargin;
        lp.rightMargin = (int) viewPosInfo.marginInfo.rightMargin;
        lp.bottomMargin = (int) viewPosInfo.marginInfo.bottomMargin;

        //fix the bug can't set gravity  LEFT|BOTTOM  or RIGHT|TOP
//            if (lp.leftMargin == 0 && lp.topMargin == 0)
//            {
//                lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
//            }

        if(lp.rightMargin != 0){
            lp.gravity = Gravity.RIGHT;
        }else {
            lp.gravity = Gravity.LEFT;
        }

        if(lp.bottomMargin != 0){
            lp.gravity |= Gravity.BOTTOM;
        }else {
            lp.gravity |= Gravity.TOP;
        }
        addView(view, lp);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant