FrameLayout类里面没有什么东西,主要说的还是它的自身的布局参数FrameLayout.LayoutParams,布局参数类继承MarginLayoutParams。看名词就知道,就是控制view的外边距的,FrameLayout.LayoutParams本身自己定义的参数只有一个gravity。
好了,既然有了布局参数,那就会有空间的一些属性吧。首先FrameLayout也是一个View,所以他必然有Padding(view的内边距)相关属性。这里我们重点关注它的onMeasure与onLayout:
onMeasure意思就是计算出该ViewGroup的布局大小及孩子View的布局大小。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
protected
void onMeasure( int
widthMeasureSpec, int
heightMeasureSpec) { int
count = getChildCount(); final
boolean measureMatchParentChildren =
MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
mMatchParentChildren.clear();
int
maxHeight = 0 ;
int
maxWidth = 0 ;
int
childState = 0 ;
for
( int
i = 0 ; i < count; i++) {
final
View child = getChildAt(i); if
(mMeasureAllChildren || child.getVisibility() != GONE) {
measureChildWithMargins(child, widthMeasureSpec,
0 , heightMeasureSpec,
0 ); final
LayoutParams lp = (LayoutParams) child.getLayoutParams();
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
if
(measureMatchParentChildren) { if
(lp.width == LayoutParams.MATCH_PARENT || lp.height == LayoutParams.MATCH_PARENT) {
mMatchParentChildren.add(child);
}
}
}
}
// Account for padding too
maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground();
maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground();
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Check against our foreground's minimum height and width
final
Drawable drawable = getForeground(); if
(drawable != null ) {
maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
}
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
count = mMatchParentChildren.size();
if
(count > 1 ) {
for
( int
i = 0 ; i < count; i++) {
final
View child = mMatchParentChildren.get(i); final
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int
childWidthMeasureSpec; int
childHeightMeasureSpec; if
(lp.width == LayoutParams.MATCH_PARENT) { childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
getPaddingLeftWithForeground() - getPaddingRightWithForeground() -
lp.leftMargin - lp.rightMargin,
MeasureSpec.EXACTLY);
}
else { childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
getPaddingLeftWithForeground() + getPaddingRightWithForeground() +
lp.leftMargin + lp.rightMargin,
lp.width);
}
if
(lp.height == LayoutParams.MATCH_PARENT) { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
getPaddingTopWithForeground() - getPaddingBottomWithForeground() -
lp.topMargin - lp.bottomMargin,
MeasureSpec.EXACTLY);
}
else { childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
getPaddingTopWithForeground() + getPaddingBottomWithForeground() +
lp.topMargin + lp.bottomMargin,
lp.height);
}
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
protected
void onLayout( boolean
changed, int
left, int top,
int right, int
bottom) { final
int count = getChildCount();
final
int parentLeft = getPaddingLeftWithForeground();
final
int parentRight = right - left - getPaddingRightWithForeground();
final
int parentTop = getPaddingTopWithForeground();
final
int parentBottom = bottom - top - getPaddingBottomWithForeground();
mForegroundBoundsChanged =
true ; for
( int
i = 0 ; i < count; i++) {
final
View child = getChildAt(i); if
(child.getVisibility() != GONE) { final
LayoutParams lp = (LayoutParams) child.getLayoutParams();
final
int width = child.getMeasuredWidth();
final
int height = child.getMeasuredHeight();
int
childLeft; int
childTop; int
gravity = lp.gravity; if
(gravity == - 1 ) {
gravity = DEFAULT_CHILD_GRAVITY;
}
final
int layoutDirection = getResolvedLayoutDirection();
final
int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
final
int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
switch
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case
Gravity.LEFT: childLeft = parentLeft + lp.leftMargin;
break ;
case
Gravity.CENTER_HORIZONTAL: childLeft = parentLeft + (parentRight - parentLeft - width) /
2 + lp.leftMargin - lp.rightMargin;
break ;
case
Gravity.RIGHT: childLeft = parentRight - width - lp.rightMargin;
break ;
default :
childLeft = parentLeft + lp.leftMargin;
}
switch
(verticalGravity) { case
Gravity.TOP: childTop = parentTop + lp.topMargin;
break ;
case
Gravity.CENTER_VERTICAL: childTop = parentTop + (parentBottom - parentTop - height) /
2 + lp.topMargin - lp.bottomMargin;
break ;
case
Gravity.BOTTOM: childTop = parentBottom - height - lp.bottomMargin;
break ;
default :
childTop = parentTop + lp.topMargin;
}
child.layout(childLeft, childTop, childLeft + width, childTop + height);
}
}
} |
哎,怎么感觉自己写着写着,还把问题说复杂了点,感觉还是看代码能明白。
还有,我在2.2版本的代码上,gravity与margin属性必须同时设置,margin才能发挥作用,如果只有margin属性而没有设置gravity,就没有效果。如果有谁知道,欢迎指教哈。
在上一篇中说了下android里drag and drop 一个View,当时那个imageView放在一个LinearLayout里面,事实上放在FrameLayout同样适用,因为他们的布局参数都继承 MarginLayoutParams类,所以通过margin控制他们的布局位置同样在FrameLayout使用。事实上 GridLayout,LinearLayout,RelativeLayout,FrameLayout的布局参数都是继承 MarginLayoutParams的。
原文:http://www.cnblogs.com/slider/archive/2011/12/30/2302413.html