上一篇从树的分支这个角度对代码进行了拓展优化,使其能够支持n叉树有效性的检查。本篇来讲解如何更好地支持树形布局的Padding。
View是不支持Padding的,而ViewGroup是支持Padding的。在给属性布局添加Padding参数时“意外地”发现了一个Bug。 可以看到继承自ViewGroup的树形布局本身是可以让子控件支持Padding的,但是绘制的连接线却不支持Padding。这是因为在绘制连接线的时候并没有把Padding考虑进去。
这里首先需要了解三个关键的方法,save,restore及clipRect。 clipRect用于剪切画布,而save和restore需要成对使用。save方法用于保存画布的各种参数,画布经过了平移、旋转、裁剪等一系列改动后,可以通过restore方法恢复到save时的状态。
了解了它们后,接下来在原有的基础上对连接线绘制进行修改,代码如下:
protected void onDrawConnectLine(Canvas canvas){ //1.1 canvas.save(); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); int scrollX = getScrollX(); int scrollY = getScrollY(); mPaddingClipRect.left = scrollX + paddingLeft; mPaddingClipRect.top = scrollY + paddingTop; mPaddingClipRect.right = scrollX + getWidth() - paddingRight; mPaddingClipRect.bottom = scrollY + getHeight() - paddingBottom; //2 canvas.clipRect(mPaddingClipRect); View root = getChildAt(0); mStartRect.left = root.getLeft(); mStartRect.right = root.getRight(); mStartRect.top = root.getTop(); mStartRect.bottom = root.getBottom(); for(int i = 1;i < getChildCount();i++){ View child = getChildAt(i); if(child.getVisibility() == View.GONE){ continue; } mEndRect.left = child.getLeft(); mEndRect.right = child.getRight(); mEndRect.top = child.getTop(); mEndRect.bottom = child.getBottom(); mLineDrawer.onDrawLine(canvas,mPaint,mStartRect,mEndRect,mTreeDirection); } //1.2 canvas.restore(); }代码1.1和1.2需要成对出现,在它们之间可以对画布的各种参数进行改动。
因为树形布局在解锁后是可以拖拽的,所以在布局拖拽的时候,裁剪的范围也得跟着移动。
修改好了再来看看效果。 如此一来,树形布局就完全支持Padding了。
本次优化对代码改动较多,感兴趣的朋友可以到Github项目中阅读完整代码。
下一篇讲解如何通过策略模式、装饰模式和工厂方法模式来进一步优化代码。