今天我们来对ExtJS 4.2 的布局(Layout)进行一次系统的学习。在ExtJS 4.2中,提供了十几种布局,我们可以在api中看到:
在这些布局中,我们常用的有Accordion、Border、Column、Fit、Form等。下面我们来看一下具体的用法。
Auto Layout
Auto Layout 是ExtJS 容器的默认布局,当我们定义一个panel的时候,如果没有指定panel的布局,那么它就会使用Auto Layout来组织子元素。
Auto Layout 的用法
var panel = Ext.create("Ext.panel.Panel", { title: "Auto Layout", 500, height: 400, items: [ { xtype: "panel", title: "第一个子Panel", 200, height: 100 }, { xtype: "panel", title: "第二个子Panel", 150, height: 100 }, { xtype: "textfield", 300, fieldLabel: "请输入用户名" } ], renderTo: "container" });
Auto Layout 本身不包含任何特殊的布局功能,它只是提供了一种调用子元素布局系统的通道。
Anchor Layout
Anchor布局将使组件固定于父容器的某一个位置,使用anchor布局的子组件尺寸相对于容器的尺寸,即父容器容器的大小发生变化时,使用anchor布局的组件会根据规定的规则重新渲染位置和大小。
AnchorLayout布局没有任何的直接配置选项(继承的除外),然而在使用AnchorLayout布局时,其子组件都有一个anchor属性,用来配置此子组件在父容器中所处的位置。
Anchor属性为一组字符串,可以使用百分比或者是-数字来表示。配置字符串使用空格隔开,例如:
- anchor:'75% 25%',表示宽度为父容器的75%,高度为父容器的25%
- anchor:'-295 -300',表示组件相对于父容器右边距为295,相对于父容器的底部位300
- anchor:'-250 10%',混合模式,表示组件党对于如容器右边为250,高度为父容器的10%
Anchor Layout 用法:
var panel = Ext.create("Ext.panel.Panel", { 500, height: 400, title: "Anchor布局", layout: "anchor", x: 60, y: 80, renderTo: "container", items: [ { xtype: 'panel', title: '75% Width and 25% Height', anchor: '75% 25%' }, { xtype: 'panel', title: 'Offset -300 Width & -200 Height', anchor: '-295 -300' }, { xtype: 'panel', title: 'Mixed Offset and Percent', anchor: '-250 10%' } ] });
Absolute Layout
Absolute Layout 继承自 Anchor Layout,并增加了X/Y配置选项对子组件进行定位,Absolute布局的目的是为了扩展布局的属性,使得布局更容易使用。
Absolute Layout 用法:
Ext.create('Ext.form.Panel', { title: 'Absolute Layout', 400, height: 275, layout: 'absolute', url: 'save-form.php', defaultType: 'textfield', items: [ { x: 10, y: 10, xtype: 'label', text: 'Send To:' }, { x: 80, y: 10, name: 'to', anchor: '90%' }, { x: 10, y: 40, xtype: 'label', text: 'Subject:' }, { x: 80, y: 40, name: 'subject', anchor: '90%' }, { x: 0, y: 80, xtype: 'textareafield', name: 'msg', anchor: '100% 100%' } ], renderTo: 'container' });
Column Layout
Column 布局用来创建一个多列的布局格式,列宽度可以使用像素值或百分比。
Column布局支持一个columnWidth属性,在布局过程中,使用columnWidth指定每个面板的宽度的百分比,他们的和加起来为1。
columnWidth和width可混合使用,这个时候系统将减去width占用的宽度,然后再根据百分比计算列的宽度。
另外,如果任何子面板没有指定columnWidth值,那么它将占满剩余的空间。
Column Layout 用法:
// 所有列都是百分比,他们的和加起来为1 Ext.create('Ext.panel.Panel', { title: 'Column Layout', 350, height: 250, layout: 'column', items: [{ title: 'Column 1', columnWidth: 0.25 }, { title: 'Column 2', columnWidth: 0.55 }, { title: 'Column 3', columnWidth: 0.20 }], renderTo: "container" }); // width和columnWidth混合使用 Ext.create('Ext.Panel', { title: 'Column Layout - Mixed', 350, height: 250, layout: 'column', items: [{ title: 'Column 1', 120 }, { title: 'Column 2', columnWidth: 0.7 }, { title: 'Column 3', columnWidth: 0.3 }], renderTo: "container" });
Border Layout
Border 布局将界面分为上下左右中五个区域,分别用north、south、west、east、center来表示,它的每个子项用region指定元素的位置。
虽然Border布局看上去比较麻烦,但用起来却非常简单
var panel = Ext.create("Ext.panel.Panel", { 500, height: 300, title: 'Border Layout', layout: 'border', items: [{ title: 'South Region (可调整大小)', region: 'south', // 所在的位置 xtype: 'panel', height: 100, split: true, // 允许调整大小 margins: '0 5 5 5' }, { title: 'West Region (可折叠/展开)', region: 'west', xtype: 'panel', margins: '5 0 0 5', 200, collapsible: true, // 可折叠/展开 id: 'west-region-container', layout: 'fit' }, { title: 'Center Region (必须)', region: 'center', // 必须指定中间区域 xtype: 'panel', layout: 'fit', margins: '5 5 0 0' }], renderTo: "container" });
Accordion Layout
Accordion Layout 是将其子元素以手风琴的效果显示。
它的子元素必须是panel,或者panel的子类。
Accordion Layout 的使用非常普遍,我们来一个简单的示例:
var panel = Ext.create("Ext.panel.Panel", { title: "Accordion Layout", 300, height: 300, defaults: { // 应用到所有子panel bodyStyle: 'padding:15px' }, layout: { // 布局配置 type: 'accordion', titleCollapse: false, animate: true, activeOnTop: true }, items: [{ title: 'Panel 1', html: 'Panel content!' }, { title: 'Panel 2', html: 'Panel content!' }, { title: 'Panel 3', html: 'Panel content!' }], renderTo: "container" });
Card Layout
Card 布局是一种向导试的布局方式,它在显示的时候,本身是没有上一步、下一步按钮的,但提供了上一步、下一步的操作方法,我们需要在界面中添加导航按钮来配合实际的业务需要。
示例代码如下:
var navigate = function (panel, direction) { var layout = panel.getLayout(); layout[direction](); Ext.getCmp('move-prev').setDisabled(!layout.getPrev()); Ext.getCmp('move-next').setDisabled(!layout.getNext()); }; var panel = Ext.create('Ext.panel.Panel', { title: '示例向导, x: 50, y: 50, 300, height: 200, layout: 'card', bodyStyle: 'padding:15px', defaults: { border: false }, bbar: [ { id: 'move-prev', text: '上一步', handler: function (btn) { navigate(btn.up("panel"), "prev"); }, disabled: true }, '->', { id: 'move-next', text: '下一步', handler: function (btn) { navigate(btn.up("panel"), "next"); } } ], items: [{ id: 'card-0', html: '<p>第一步</p>' }, { id: 'card-1', html: '<p>第二步</p>' }, { id: 'card-2', html: '<p>第三步</p>' }], renderTo: "container" });
Fit Layout
Fit Layout 是很常用的一种布局,在Fit布局中,子元素将自动填满整个父容器。
在Fit 布局下,对其子元素设置宽度是无效的。如果在Fit 布局中放置了多个组件,则只会显示第一个子元素。典型的案例就是当客户要求一个window或panel中放置一个GRID组件,grid组件的大小会随着父容器的大小改变而改变。
Fit Layout 示例代码:
var panel = Ext.create("Ext.panel.Panel", { title: 'Fit Layout', x: 30, y: 30, 300, height: 150, layout: 'fit', items: { title: '内部Panel', html: '内部Panel 的内容', bodyPadding: 20, border: false }, renderTo: "container" });
Form Layout
Form Layout 用来组织表单字段的,Form Layout 下的表单字段会被拉伸到表单的宽度。
示例代码如下
var panel = Ext.create("Ext.panel.Panel", { 350, height: 240, title: "FormLayout Panel", layout: 'form', bodyPadding: 5, defaultType: 'textfield', items: [{ fieldLabel: '姓名', name: 'name', allowBlank: false }, { fieldLabel: '公司', name: 'company' }, { fieldLabel: 'Email', name: 'email', vtype: 'email' }, { fieldLabel: '年龄', name: 'age', xtype: 'numberfield', minValue: 0, maxValue: 100 }], renderTo: "container" });
Table Layout
Table Layout 将内容绘制在table标签中,table的列数可以指定,还可以通过设置rowSpan和colSpan来创建复杂的布局。
示例代码如下:
var panel = Ext.create("Ext.panel.Panel", { title: 'Table Layout', 300, height: 150, layout: { type: 'table', // 列数 columns: 3 }, defaults: { bodyStyle: 'padding:20px' }, items: [{ html: 'Cell A content', rowspan: 2 //占用两行 }, { html: 'Cell B content', colspan: 2 //占用两列 }, { html: 'Cell C content', cellCls: 'highlight' }, { html: 'Cell D content' }], renderTo: "container" });
Box Layout
Box Layout 是HBox Layout 和 VBox Layout 的父类,一般不会直接用到。
HBox Layout
HBox Layout 将子元素放在同一水平位置,通过align设置子元素的对齐方式,对齐方式有:
- top : 默认的对其方式,顶部对齐
- middle : 中间对齐
- bottom : 底部对齐
- stretch : 拉伸对齐,所有子元素根据父容器的高度拉伸
- stretchmax : 拉伸对齐,所有子元素根据子元素中最高的高度拉伸
示例代码如下:
var panel = Ext.create("Ext.panel.Panel", { 500, height: 300, title: "HBoxLayout Panel", layout: { type: 'hbox', align: 'stretch' }, items: [{ xtype: 'panel', title: 'Inner Panel One', flex: 2 }, { xtype: 'panel', title: 'Inner Panel Two', flex: 1 }, { xtype: 'panel', title: 'Inner Panel Three', flex: 1 }], renderTo: "container" });
VBox Layout
VBox Layout 以垂直的方式组织所有子元素。它的子元素可以通过align属性来设置对齐方式,vbox的对齐方式有:
- left : 左对齐,默认对其方式
- center : 中间对齐
- right : 右对齐
- stretch : 以父容器的宽度拉伸对齐
- stretchmax : 以所有子元素中的最大宽度拉伸对齐
示例代码如下:
var panel = Ext.create("Ext.panel.Panel", { 500, height: 400, title: "VBoxLayout Panel", layout: { type: 'vbox', align: 'center' }, items: [{ xtype: 'panel', title: 'Inner Panel One', 250, flex: 2 }, { xtype: 'panel', title: 'Inner Panel Two', 250, flex: 4 }, { xtype: 'panel', title: 'Inner Panel Three', '50%', flex: 4 }], renderTo: "container" });