【问题标题】:ExtJS 4 Two collapsible panels with splitterExtJS 4 两个带分离器的可折叠面板
【发布时间】:2017-09-13 11:05:25
【问题描述】:

我有一个带有两个面板的容器作为它的项目。我希望两个面板都是可折叠的(同时没有一个面板或只有一个面板可以折叠),如果任何面板折叠,其他面板应该占用所有剩余空间。我还希望能够使用Ext.resizer.Splitter 调整两个面板的大小。

我尝试了不同的 (h/v)box/border 布局组合,但没有一个能正常工作。

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

Check this fiddle

另外,我希望能够使用 single Ext.resizer.Splitter 折叠两个面板,但我可以看到它没有开箱即用,我必须覆盖它.我说的对吗?

我使用的是 ExtJS 版本 4.2.1。

【问题讨论】:

  • 所以您想要类似accordion 但能够折叠所有项目的东西?
  • @scebotari66 是的,类似的,但是Ext.resizer.Splitter。实际上,我几乎忘记了手风琴布局!也许我可以以某种方式将它与拆分器集成......
  • 如果您觉得这个问题不正确,请写下原因。不要只是投反对票。

标签: extjs extjs4


【解决方案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 属性告诉它们彼此占用多少空间)。 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 上,此容器将现有子面板设置为始终保持倒数第二个折叠面板处于展开状态。您应该修改算法以满足您的需要。

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

【讨论】:

  • 首先,感谢您的回答!这个决定一般适合我,但我一直在寻找更通用的解决方案,我会等到赏金期结束,如果没有出现更合适的解决方案,我会奖励你。还有一句话 - 如果其中一个面板折叠并且我尝试折叠第二个面板,则会出现错误。
  • 我在测试样品时没有重现任何错误。你能告诉我哪个是错误吗?如果您想要一个通用的解决方案,您应该使用控制器来监听面板的折叠/展开事件并跟踪那些关闭的事件。这样,您可以通过在折叠最后一个打开的面板时手动调用panel.expand() 来强制至少打开一个面板!我相信您可以使用自定义插件实现相同的解决方案。
  • 您可以在此处检查错误 - fiddle.sencha.com/#view/editor&fiddle/2758。只需折叠第一个面板,然后折叠第二个面板。
  • 通过更通用的解决方案,我的意思是覆盖框布局/拆分器/任何东西。无论如何,我真的很感谢你的回答!
  • 看来我的解决方案对您在两个面板中添加的 animCollapse: false 属性过敏。删除它会按预期工作。我会努力解决的
【解决方案2】:

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

解决方案有点原始,您可以在this fiddle查看。

【讨论】:

    【解决方案3】:

    在 ExtJs 中有 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'
         }]
     });
    

    【讨论】:

    • Myabe 我错过了一些东西,但你的答案似乎与我接受的答案重复,但忽略我问题的这一部分“同时没有一个或只有一个面板可以折叠”。跨度>
    • 因此您可以设置条件,在折叠事件之前只能折叠一个面板。在折叠事件之前,您可以检查一个是否已经折叠而不是返回 false。所以事件不会执行。
    • 是的,像这样的解决方案已经在接受的答案中描述。你读过吗?
    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2013-11-24
    • 2014-06-22
    • 2015-11-25
    • 1970-01-01
    相关资源
    最近更新 更多