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