Does this help?
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();
}
}
}]
});
}});
Here vbox is used to set the panels vertically (the flex property tells them how much space to take from each other). The collapsible property set to true makes them collapsible. Then each panel has an event that expands the sibling panel when the target panel collapses. With this, at least one panel is always expanded and you can resize them with the splitter!
Edit 1:
The previous code sample isn't generic and does not react as expected if we set panels with animCollapse: false. A generic solution would look like the following:
// 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'
}]
});
}
});
Here we create an extended container that uses vbox layout to set the panels vertically. On initComponent, this container setups the existing children panels to always keep the penultimate collapsed panel expanded. You should modify the algorithm to suit your needs.
Sidenote: it isn't ideal to set variables on the view container. These variables should be moved into a controller.
Ext.resizer.Splitter. Actually, I almost forgot about accordion layout! Maybe I can integrate it with splitter in some way... - Sergey Novikov