ExtJS 4 两个带拆分器的可折叠面板

ExtJS 4 Two collapsible panels with splitter

我有一个带有两个面板的容器作为它的项目。我希望两个面板都是可折叠的(同时不能折叠一个面板或只能折叠一个面板),如果任何面板折叠,另一个面板应该占用所有剩余的面板 space。此外,我希望能够使用 Ext.resizer.Splitter.

调整两个面板的大小

我尝试了不同的 (h/v)box/border 布局组合,但其中 none 可以正常工作。

似乎 Ext.layout.container.Accordion 是我所需要的,但正如我所见,开箱即用 Ext.resizer.Splitter。

Check this fiddle

此外,我希望能够使用 single Ext.resizer.Splitter 折叠两个面板,但正如我所见,它不可用框,我必须覆盖它。我说的对吗?

我正在使用 ExtJS 版本 4.2.1。

这有帮助吗?

Ext.application({
name: 'Fiddle',

launch: function () {

    Ext.create('Ext.Container', {
        height: 500,
        renderTo: Ext.getBody(),
        width: 500,
        layout: {
            type: 'vbox',
            align: 'stretch'
        },

        items: [{
            xtype: 'panel',
            reference: 'panel1',
            title: 'Top panel',
            collapsible: true,  // To allow collapse
            flex: 1,
            bodyStyle: 'background: #dadada',
            listeners: {
                collapse: function(){
                    this.up().down("[reference='panel2']").expand();
                }
            }
        }, 
        {
            xtype: 'splitter' 
        },
        {
            xtype: 'panel',
            reference: 'panel2',
            title: 'Bottom panel',
            collapsible: true,  // To allow collapse
            flex: 1,
            bodyStyle: 'background: #999',
            listeners: {
                collapse: function(){
                    this.up().down("[reference='panel1']").expand();
                }
            }
        }]

    });
}});

这里的vbox是用来垂直设置面板的(flex属性告诉他们space可以互相取多少)。 collapsible 属性 设置为 true 使它们可折叠。然后每个面板都有一个事件,当目标面板折叠时展开同级面板。这样一来,至少有一个面板始终处于展开状态,您可以使用拆分器调整它们的大小!


编辑 1:

前面的代码示例不是通用的,如果我们使用 animCollapse: false 设置面板,它不会按预期做出反应。通用解决方案如下所示:

// Our extended container
Ext.define('MyVboxContainer', {
    extend: 'Ext.Container',

    layout: {
        type: 'vbox',
        align: 'stretch'
    },

    // We do the setup on initiating the component
    initComponent: function () {
        var me = this;
        var panelCount = 0;

        // For each child component
        this.items.forEach(function (comp) {

            // If the component is a panel
            if (comp.xtype === 'panel') {

                // We add an unique ref
                comp.reference = 'panel' + panelCount;

                // Increment the total number of panels
                panelCount++

                // And listeners for beforecollapse, collapse and expand
                comp.listeners = {
                    // On collpase, we track the last collapsed panel
                    'collapse': function () {
                        me.closedCount++;

                        me.lastClosed = this.reference;
                    },

                    // On expand we decrement the total number of panels collapsed
                    'expand': function () {
                        me.closedCount--;
                    },

                    // If this is the last panel being collapsed,
                    // we expand the previous collapsed panel
                    // Note: this cannot be done on the expand event
                    // if the panel has animCollapse: false
                    'beforecollapse': function () {
                        if (me.closedCount + 1 == me.totalPanels) {
                            me.down("[reference='" + me.lastClosed + "']").expand();
                        }
                    }
                };
            }
        });

        this.totalPanels = panelCount; // total number of panels
        this.lastClosed = null; // Last collapsed panel
        this.closedCount = 0; // How many panels we have closed

        console.log("Total panels are: " + this.totalPanels)

        this.callParent();
    }
});

Ext.application({
    name: 'Fiddle',

    launch: function () {

        Ext.create('MyVboxContainer', {
            height: 500,
            width: 500,
            renderTo: Ext.getBody(),

            items: [{
                xtype: 'panel',
                animCollapse: false,
                title: 'Top panel',
                collapsible: true, // To allow collapse
                flex: 1,
                bodyStyle: 'background: #dadada'
            }, {
                xtype: 'splitter'
            }, {
                xtype: 'panel',
                title: 'Middle panel',
                animCollapse: false,
                collapsible: true, // To allow collapse
                flex: 1,
                bodyStyle: 'background: #999'
            }, {
                xtype: 'splitter'
            }, {
                xtype: 'panel',
                title: 'Bottom panel',
                animCollapse: false,
                collapsible: true, // To allow collapse
                flex: 1,
                bodyStyle: 'background: #999'
            }]
        });
    }
});

这里我们创建了一个扩展容器,它使用 vbox 布局来垂直设置面板。在 initComponent,此容器将现有的子面板设置为始终保持 倒数第二个折叠的面板展开。您应该修改算法以满足您的需要。

旁注:在视图容器上设置变量并不理想。这些变量应该移到控制器中。

我根据 Ext.resizer.Splitter 代码编写了组件。它允许使用单个拆分器折叠两个面板。

解决方案有点原始,您可以在 this fiddle.

中查看

In ExtJs have spliter.

您可以在容器内使用。在这里,我创建了一个带有 collapsible 面板的演示。

希望对您解决问题有所帮助。 Sencha Fiddle

Ext.create('Ext.container.Container', {
     height: 300,
     layout: {
         type: 'vbox',
         align: 'stretch'
     },
     width: 400,
     renderTo: Ext.getBody(),
     border: 1,
     items: [{
         xtype: 'panel',
         collapsible: true,
         title: 'First Panel',
         flex: 1
     }, {
         xtype: 'splitter',
         height: 20
     }, {
         xtype: 'panel',
         collapsible: true,
         flex: 1,
         maintainFlex: true,
         title: 'Second Panel'
     }]
 });