BorderLayout是一個限制性布局,它只允許在東顽腾、南、西诺核、北和中心五大區(qū)域內(nèi)去放置組件崔泵,每個區(qū)域至多一個組件.雖然感覺這個布局在實際使用中被使用到的情況不多,但是我們還是來看下它的主要實現(xiàn)吧:
BorderLayout核心方法
preferredLayoutSize
- 這個方法在布局之前就會調(diào)用來確定大小尺寸.
public Dimension preferredLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
//初始化盒子尺寸類
Dimension dim = new Dimension(0, 0);
//布局是否是LTR模式
boolean ltr = target.getComponentOrientation().isLeftToRight();
//組件
Component c = null;
//根據(jù)布局方向返回EAST的布局
if ((c = getChild(EAST, ltr)) != null) {
//獲取組件的預(yù)設(shè)尺寸大小
Dimension d = c.getPreferredSize();
//更新盒子的寬度(加上組件的寬度和水平間隙)
dim.width += d.width + hgap;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回WEST的布局
if ((c = getChild(WEST, ltr)) != null) {
//獲取組件的預(yù)設(shè)尺寸大小
Dimension d = c.getPreferredSize();
//更新盒子的寬度(加上組件的寬度和水平間隙)
dim.width += d.width + hgap;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回CENTER的布局
if ((c = getChild(CENTER, ltr)) != null) {
//獲取組件的預(yù)設(shè)尺寸大小
Dimension d = c.getPreferredSize();
//更新盒子的寬度(加上組件的寬度)
dim.width += d.width;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回NORTH的布局
if ((c = getChild(NORTH, ltr)) != null) {
//獲取組件的預(yù)設(shè)尺寸大小
Dimension d = c.getPreferredSize();
//更新盒子的寬度(現(xiàn)有寬度和組件的寬度的最大值)
dim.width = Math.max(d.width, dim.width);
//更新盒子的高度(加上組件高度和垂直間隙)
dim.height += d.height + vgap;
}
//根據(jù)布局方向返回SOUTH的布局
if ((c = getChild(SOUTH, ltr)) != null) {
//獲取組件的預(yù)設(shè)尺寸大小
Dimension d = c.getPreferredSize();
//更新盒子的寬度(現(xiàn)有寬度和組件的寬度的最大值)
dim.width = Math.max(d.width, dim.width);
//更新盒子的高度(加上組件高度和垂直間隙)
dim.height += d.height + vgap;
}
//最后再加上容器四周的內(nèi)間距即可得出所需的尺寸大小
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
minimumLayoutSize
- 這個方法用途是在計算布局所需的最小尺寸大小
public Dimension minimumLayoutSize(Container target) {
synchronized (target.getTreeLock()) {
//初始化盒子尺寸類
Dimension dim = new Dimension(0, 0);
//布局是否是LTR模式
boolean ltr = target.getComponentOrientation().isLeftToRight();
//組件
Component c = null;
//根據(jù)布局方向返回EAST的布局
if ((c = getChild(EAST, ltr)) != null) {
//獲得組件的最小尺寸
Dimension d = c.getMinimumSize();
//更新盒子的寬度(加上組件的寬度和水平間隙)
dim.width += d.width + hgap;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回WEST的布局
if ((c = getChild(WEST, ltr)) != null) {
//獲得組件的最小尺寸
Dimension d = c.getMinimumSize();
//更新盒子的寬度(加上組件的寬度和水平間隙)
dim.width += d.width + hgap;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回CENTER的布局
if ((c = getChild(CENTER, ltr)) != null) {
//獲得組件的最小尺寸
Dimension d = c.getMinimumSize();
//更新盒子的寬度(加上組件的寬度)
dim.width += d.width;
//更新盒子的高度(現(xiàn)有高度和組件的高度的最大值)
dim.height = Math.max(d.height, dim.height);
}
//根據(jù)布局方向返回NORTH的布局
if ((c = getChild(NORTH, ltr)) != null) {
//獲得組件的最小尺寸
Dimension d = c.getMinimumSize();
//更新盒子的寬度(現(xiàn)有寬度和組件的寬度的最大值)
dim.width = Math.max(d.width, dim.width);
//更新盒子的高度(加上組件高度和垂直間隙)
dim.height += d.height + vgap;
}
//根據(jù)布局方向返回SOUTH的布局
if ((c = getChild(SOUTH, ltr)) != null) {
//獲得組件的最小尺寸
Dimension d = c.getMinimumSize();
//更新盒子的寬度(現(xiàn)有寬度和組件的寬度的最大值)
dim.width = Math.max(d.width, dim.width);
//更新盒子的高度(加上組件高度和垂直間隙)
dim.height += d.height + vgap;
}
//最后再加上容器四周的內(nèi)間距即可得出所需的尺寸大小
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
layoutContainer
- 這個方法和Android中的onLayout方法很相似猪瞬,因為它也是在父類Container也是onLayout方法中調(diào)用的憎瘸。
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
//獲取容器的四周內(nèi)間距
Insets insets = target.getInsets();
//容器頂部
int top = insets.top;
//容器底部(減去底部內(nèi)間隙)
int bottom = target.height - insets.bottom;
//容器左邊
int left = insets.left;
//容器右邊(容器寬度減去右間隙)
int right = target.width - insets.right;
//是否是LTR模式
boolean ltr = target.getComponentOrientation().isLeftToRight();
Component c = null;
//根據(jù)布局方向返回NORTH的布局
if ((c = getChild(NORTH, ltr)) != null) {
//設(shè)置組件的寬高(寬會被拉伸)
c.setSize(right - left, c.height);
//獲取預(yù)設(shè)尺寸
Dimension d = c.getPreferredSize();
//設(shè)置位置
c.setBounds(left, top, right - left, d.height);
//因為已經(jīng)在NORTH方位上放置了組件,所以頂部應(yīng)該向下偏移(偏移量:組件的高度加垂直間隙)
top += d.height + vgap;
}
//根據(jù)布局方向返回SOUTH的布局
if ((c = getChild(SOUTH, ltr)) != null) {
//設(shè)置組件的寬高(寬會被拉伸)
c.setSize(right - left, c.height);
//獲取預(yù)設(shè)尺寸
Dimension d = c.getPreferredSize();
//設(shè)置位置
c.setBounds(left, bottom - d.height, right - left, d.height);
//因為在SOUTH方位上放置了組件,所以底部應(yīng)該向上偏移(偏移量:組件的高度加垂直間隙)
bottom -= d.height + vgap;
}
//根據(jù)布局方向返回EAST的布局
if ((c = getChild(EAST, ltr)) != null) {
//設(shè)置組件的寬高(高會被拉伸)
c.setSize(c.width, bottom - top);
//獲取預(yù)設(shè)尺寸
Dimension d = c.getPreferredSize();
//設(shè)置位置
c.setBounds(right - d.width, top, d.width, bottom - top);
//因為在EAST方位上放置了組件,所以右邊應(yīng)該向左偏移(偏移量:組件的寬度加上水平間隙)
right -= d.width + hgap;
}
//根據(jù)布局方向返回WEST的布局
if ((c = getChild(WEST, ltr)) != null) {
//設(shè)置組件的寬高(高會被拉伸)
c.setSize(c.width, bottom - top);
//獲取預(yù)設(shè)尺寸
Dimension d = c.getPreferredSize();
//設(shè)置位置
c.setBounds(left, top, d.width, bottom - top);
//因為在WEST方位上放置了組件,所以左邊邊應(yīng)該向右偏移(偏移量:組件的寬度加上水平間隙)
left += d.width + hgap;
}
//根據(jù)布局方向返回CENTER的布局
if ((c = getChild(CENTER, ltr)) != null) {
//設(shè)置位置
c.setBounds(left, top, right - left, bottom - top);
}
}
}
getChild
- 這個方法根據(jù)相應(yīng)的常數(shù)和布局方向獲取對應(yīng)的組件
private Component getChild(String key, boolean ltr) {
Component result = null;
//在NORTH和SOUTH情況下不受LTR影響
if (key == NORTH) {
//在NORTH情況下 再進(jìn)行判斷是否使用了firstLine,根據(jù)規(guī)則優(yōu)先返回firstLine
result = (firstLine != null) ? firstLine : north;
} else if (key == SOUTH) {
//在SOUTH情況下 再進(jìn)行判斷是否使用了lastLine,根據(jù)規(guī)則優(yōu)先返回lastLine
result = (lastLine != null) ? lastLine : south;
} else if (key == WEST) {
//在SOUTH情況下判斷布局方向 根據(jù)布局方向返回對應(yīng)的值
result = ltr ? firstItem : lastItem;
if (result == null) {
//如果為空則說明沒有使用優(yōu)先字段firstItem/lastItem
result = west;
}
} else if (key == EAST) {
//在EAST情況下判斷布局方向 根據(jù)布局方向返回對應(yīng)的值
result = ltr ? lastItem : firstItem;
if (result == null) {
//如果為空則說明沒有使用優(yōu)先字段firstItem/lastItem
result = east;
}
} else if (key == CENTER) {
//在CENTERT情況下直接返回對應(yīng)的值
result = center;
}
if (result != null && !result.visible) {
//如果組件非可視化的返回null
result = null;
}
return result;
}
注:firstLine, lastLine, firstItem, lastItem,center相對定位常數(shù),可以代替北,難,東,西或者中心混合使用兩種常數(shù)會導(dǎo)致不可預(yù)料的結(jié)果。如果你使用了這兩種類型,相對常數(shù)將優(yōu)先陈瘦。例如:如果在方向為左到右的容器中添加使用NORTH和BEFORE_FIRST_LINE常量, 則只有BEFORE_FIRST_LINE將被布局