上一篇讲解了树形布局拖拽效果的实现,到上一篇为止树形布局的功能就基本实现了。本篇从树的分支这个角度来对树形布局的代码进行优化。
思路解析
以三叉树为例,三叉树所有结点的分支数都在0~3这个范围内。某结点有三个分支,如果再插入一个子结点就破坏了三叉树的定义。
在树形布局里,我们也可以给它添加这样的检查机制,使之成为严格的n叉树,在运行的时候如果破坏了这种分支数限制就抛出异常,这样就可以让开发者严格遵守n叉树的规则了。
基本实现
首先先定义分支数属性。
<resources>
<declare-styleable name="TreeView">
...
<attr name="branch" format="integer"/>
</declare-styleable>
</resources>
private static final int BRENCH_INFINATE = -1;
private int mMaxBranch;
private void init(Context context,AttributeSet attrs){
...
mMaxBranch = typedArray.getInt(R.styleable.TreeView_branch,BRENCH_INFINATE);
...
}
从代码里可以看出,默认情况下树形布局并没有对分支树进行限制,也就是说它不是一颗n叉树。
接着在定义一个异常类,在n叉树分支规则被破坏时抛出。
private static class TreeException extends RuntimeException{
public TreeException(String message) {
super(message);
}
}
下面是检查分支数的代码。
private void checkBranch(){
if(mMaxBranch == BRENCH_INFINATE){
return;
}
int branchCount = getChildCount() - 1;
if(branchCount > mMaxBranch){
throw new TreeException("this is a " + mMaxBranch + " fork tree,however it's count of branch is " + branchCount);
}
}
布局类控件可以通过addView方法动态增加子控件,这个方法会调用requestLayout方法,进而触发整个布局重新测量、摆放以及绘制。所以接下来只要在onMeasure方法里调用checkBranch方法就行了。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
checkBranch();
measureChildren(widthMeasureSpec,heightMeasureSpec);
if(mTreeDirection == DIRECTION_LEFT_TO_RIGHT || mTreeDirection == DIRECTION_RIGHT_TO_LEFT){
measureHorizontal(widthMeasureSpec,heightMeasureSpec);
}else{
measureVertical(widthMeasureSpec,heightMeasureSpec);
}
}
测试
现在在一个二叉树里放三个分支。
<com.pyjtlk.widget.TreeLayout
android:id="@+id/treeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A00"
app:treeDirection="leftToRight"
app:branch="2"
app:levelInterval="50dp">
<!--根结点-->
<View
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#A0A"/>
<!--分支结点1-->
<View
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#A0A"/>
<!--分支结点2-->
<View
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#A0A"/>
<!--分支结点3-->
<View
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#A0A"/>
</com.pyjtlk.widget.TreeLayout>
果然报错了,三个分支破坏了二叉树的定义。
最后
对完整代码感兴趣的朋友可以看看Github项目
下一篇讲解Padding支持的优化