Layout布局源码浅析之——FrameLayout

一直想研究下安卓各种布局控件,FrameLayout是安卓最简单的界面布局,所以就从FrameLayout讲起。

1.属性。frameLayout继承ViewGroup,除了拥有ViewGroup的属性之外,只有一个layout_gravity属性。看它的内部静态类LayoutParams:

 
1 public static class LayoutParams extends MarginLayoutParams {  
2     public int gravity = -1;//唯一的属性  

2.绘制过程。首先,它会遍历所有子view,并且对每个子view进行measure,并记录下子view的最大宽高,作为自身的尺寸。在这个过程中,如果自身是不确定大小的模式,子view又是MATCH_PARENT属性的,就需要为这些子view重新测绘。

 1 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
 2        (。。。。。。)  
 3   
 4        int maxHeight = 0;//记录最大的宽高  
 5   
 6        int maxWidth = 0;  
 7        int childState = 0;  
 8   
 9        for (int i = 0; i < count; i++) {  
10            final View child = getChildAt(i);  
11            if (mMeasureAllChildren || child.getVisibility() != GONE) {  
12                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);//测绘所有子view  
13                final LayoutParams lp = (LayoutParams) child.getLayoutParams();  
14                maxWidth = Math.max(maxWidth,  
15                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);  
16                maxHeight = Math.max(maxHeight,  
17                        child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);  
18                childState = combineMeasuredStates(childState, child.getMeasuredState());  
19                if (measureMatchParentChildren) {  
20                    if (lp.width == LayoutParams.MATCH_PARENT ||  
21                            lp.height == LayoutParams.MATCH_PARENT) {  
22                        mMatchParentChildren.add(child);//保存需要重新测绘的子view  
23                    }  
24                }  
25            }  
26        }  
27   
28     (。。。。。。)  
29        if (count > 1) {  
30            for (int i = 0; i < count; i++) {  
31               <pre name="code" class="java" style="font-size: 13.3333px;">     (。。。。。。)  
32 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);//重新测绘子view } } }

3.layout过程。FrameLayout对每个子view的layout过程是相同的。它遍历所有子view,通过子view的gravity属性进行xy轴偏移量的计算,最后调用child.layout()对子View进行布局。

 1 void layoutChildren(int left, int top, int right, int bottom,  
 2                                   boolean forceLeftGravity) {  
 3         (。。。。。。)  
 4   
 5         for (int i = 0; i < count; i++) {  
 6             (。。。。。。)  
 7   
 8                 switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {  
 9                     case Gravity.CENTER_HORIZONTAL:  
10                         childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +  
11                         lp.leftMargin - lp.rightMargin;  
12                         break;  
13                     case Gravity.RIGHT:  
14                         if (!forceLeftGravity) {  
15                             childLeft = parentRight - width - lp.rightMargin;  
16                             break;  
17                         }  
18                     case Gravity.LEFT:  
19                     default:  
20                         childLeft = parentLeft + lp.leftMargin;  
21                 }  
22   
23                 switch (verticalGravity) {  
24                     case Gravity.TOP:  
25                         childTop = parentTop + lp.topMargin;  
26                         break;  
27                     case Gravity.CENTER_VERTICAL:  
28                         childTop = parentTop + (parentBottom - parentTop - height) / 2 +  
29                         lp.topMargin - lp.bottomMargin;  
30                         break;  
31                     case Gravity.BOTTOM:  
32                         childTop = parentBottom - height - lp.bottomMargin;  
33                         break;  
34                     default:  
35                         childTop = parentTop + lp.topMargin;  
36                 }  
37   
38                 child.layout(childLeft, childTop, childLeft + width, childTop + height);  
39             }  
40         }  
41     }  
posted @ 2018-06-08 20:56  linghu_java  阅读(1926)  评论(0编辑  收藏  举报