Hi Eric,
Thanks for the update, however, I'm not using PhoneGap, so I'm afraid I don't have access to it's JS-native bridge API.
I've figured out the main issue I was having. It was very subtle indeed. The set up that I have is a separate panel, which is a child of a card layout component, with a text area field and form, so that a user can post a message. They have the opportunity to submit or cancel the message. It is most probable that the virtual keyboard will be open when the cancel or submit button is pressed. If either button is pressed the panel should disappear, the keyboard should be hidden, and they should be returned to the previous screen.
On closing the panel when tapping the back button (i.e setActiveItem), thinking of being a good memory management citizen, I tried to destroy the panel that I was leaving. However, if you do this straight away the OS gets a bit confused and inadvertently fails to close the open virtual keyboard. The solution is to destroy the panel via a setTimeout call, so that the native OS keyboard code gets a moment to run. I've included an outline of the code I used to solve the problem as I'm sure this has caught a few more developers out (and it certainly took me a long time to figure out what on earth was going on).
I've also included a work-around to the 'after' event on an animation being called twice.
Code:
myapp.views.InputPopupView = Ext.extend(Ext.Panel, {
initComponent: function() {
var me = this;
this.dockedItems = [
{
xtype: 'toolbar',
dock: 'top',
defaults: {
scope: this
},
items: [
{
ui: 'default',
text: 'Cancel',
handler: this.showPreviousCard
},
{
xtype: 'spacer'
},
{
ui: 'confirm',
text: 'Save',
id: 'save-button',
handler: function() {
// Do something interesting here
this.showPreviousCard();
}
}
]
}
];
this.items = [
{
xtype : 'form',
itemId: 'myForm',
items: [
{
itemId: 'myTextArea',
xtype: 'textareafield',
name: "myValue",
placeHolder: "Enter your message",
listeners: {
afterrender : function(panel) {
this.el.down('textarea').setHeight((this.ownerCt.ownerCt.getHeight()/100*45)); // Set to 45% of screen height.
},
focus: function() {
window.scrollTo(0,1); // Force top-docked toolbar back into view. (was a problem on iPad)
}
}
}
]
}
];
myapp.views.InputPopupView.superclass.initComponent.apply(this, arguments);
},
showPreviousCard : function() {
this.ownerCt.setActiveItem(this.prevCard, { // Example code assumes that parent is using a card layout.
type: 'slide',
direction: 'down',
scope: this,
after: function() {
if(this.callSetActiveItemOnce === 0) { // Fix to stop method being called twice due to Sencha issue.
this.callSetActiveItemOnce++;
// Required to hide virtual keyboard. Do not do on Android as causes screen to jump after
// slide transition. (In my case the previous screen is a panel with scroll: 'vertical' set)
if(!Ext.is.Android) {
this.down('#myTextArea').blur();
}
// Allow virtual keyboard to disappear before destroying panel.
var me = this;
setTimeout(function() {
me.callSetActiveItemOnce = 0; // Fix to stop method being called twice due to Sencha issue.
me.destroy();
}, 500);
}
}
});
},
callSetActiveItemOnce: 0 // Fix to stop method being called twice due to Sencha issue.
});
Following CSS will ensure textareafield is displayed full width. I'm sure there must be a better way of doing this, but just including for completeness.
Code:
.x-form .x-panel-body {
padding: 0;
}