Sliding Menus became very popular on the mobile space thanks to the Facebook app. Since I developed a solution for the SenchaCon App, and got a lot of requests from attendees to make this public, here it is!
How it works
If you’re eager for the final solution just jump straight to the end. If you want to learn more, bear with me here.
The whole thing is pretty simple once you realize that the menu is always on the screen, but hidden underneath the viewport items. So, the menu is not really pushing content, but the whole content is getting out of the way.
This essentially translate to:
- Add the Menu directly to the viewport and dock it on the left
- Set top, left and bottom configs to 0. Doing so will make the menu a floating component, not taking any space from the actual content
- Make sure the Menu z-index is 0, so it will stay underneath the viewport content
- Whenever the user taps a button to open the menu, you translate the whole inner viewport to the right
Hardware Acceleration Trick
The performance for this menu is really great thanks to its simplicity and GPU acceleration. If you’ve been developing mobile for a while, you might already know that using CSS translate3d property will force hardware acceleration, since it creates a composite layer.
What might be new for you is that forcing this right from the start is better than on demand. There’s a cost in generating a composite layer. If you only create the layer (aka setting a translate3d property) once the user taps the button, it might affect the animation and rendering time. So for the SenchaCon app I prefer to pay the price upfront while the app is initializing and generate the composite layer right from the start:
.viewport-inner { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); transition: all 0.2s; }
Final Result
You can download the full source code from github.com/brunotavares/SenchaExamples
*Touch compatibility webkit onlyWhat about enabling touch dragging?
On the native Facebook menu (and in some user-extensions) users can touch and drag the toolbar to reveal the menu. This adds a lot of extra code to make the card translate follow the user finger and also calculates snapping points.
Plus, it performs great on the latest devices, but the experience on old ones is not that great. In order to keep the user experience in a great level, I just decided not to implement this part. All the comments I got were “This menu works great!” instead of “This thing is not draggable”, so I’m comfortable with the decision.
Hope you liked it :) Ping me if you have questions or found bugs! Fixes are always welcome on Github as well.
Nice one, Bruno! Can’t beat the simplicity!
Thanks for sharing this. I was looking around trying to figure it out. It seems so simple.
Great solution. I have been working on a draggable version, but have run into problems getting it to work. If I press the menu button and translate the view to reveal the menu, the main view no longer seems draggable. If you get a chance, I would enjoy seeing how you approach it.
Sencha Touch Sliding Menu – The “Facebook Menu” http://t.co/Sy5Xnh7Dw0
Sencha Touch Sliding Menu – The “Facebook Menu” : http://t.co/mePG0yG6wX
Great work.
I have two questions.
1.- Why left menu doesn’t hide ontap?
2.- How show the views for each option?
1 – It doesn’t? I’m clicking the icon to open, and again to close. It looks ok here.
2 – Each item on the side is a button, so you can wire actions to these buttons on controllers. These actions will add the views on the viewport.
Hi Bruno, very great tutorial!
I tryed to make little modification to slide the menu from the bottom line without slide up the topbar.
It works well, but it’s not smooth as the left one, the container appears immediately without any animation.
here is the code of container:
Great article, I think this is the simplest solution I found so far. Thank you. I had small issue with my architecture that during app initialisation the sliding-menu was shown momentarily (several milliseconds), same thing also happened when I did mycontainer.setActiveItem(…). This is my solution: Sencha touch sliding menu, hope it helps people with same issue.
Hi,
Can you tell me how can I use this in sencha architect. I created the menu.js but not able to add viewport.
I am new to this, please help
Thanks
Hi, What if I want it to slide from the right. What are the changes that I need to do ?
I tried few things and it got all messed up. Please help.
I figured it out: Change all config occurrences of left to right
docked: ‘right’,
right: 0,
right : this.getWidth(),
and change the translate value to negative:
if (open) {
targetEl.translate(-(this.getWidth()), 0, 0);
this.maskCmp.show();
}
Thanks for sharing !
Hi, Excelent works!
How to integrate this example to Sencha Architect 3? Pleaaaasseeee..
just Menu.js typing as a component and include Menu.css resource. next application sourece(app.js) typing
// @require @packageOverrides
Ext.Loader.setConfig({
});
Ext.application({
views: [
‘Menu’
],
name: ‘MyApp’,
launch: function() {
var viewport = Ext.Viewport;
// add extra css to viewport
Ext.Viewport.innerElement.addCls(‘viewport-inner’);
// add initial views
viewport.add([{
xtype: ‘mainmenu’
},{
xtype: ‘container’,
html: ‘Sencha Touch Example’,
padding: 10,
items: [{
xtype: ‘toolbar’,
docked: ‘top’,
title: ‘Sliding Menu’,
items: [{
iconCls: ‘more’,
handler: function() {
//alert(“aaaa”);
Ext.Viewport.child(‘mainmenu’).toggle();
}
}]
}]
}]);
}
});
Awesome! Thanks!
how do i add speaker view on the menu or any other view on the menus
can any one set this menu for RTL , right to left support for arabic as well???
Thanks
If time is money you’ve made me a welthaier woman.
Hi, Bruno! Thanks for you help, i am just learning how to develop for mobile and Sencha Touch is being very helpful for me. Sorry for the newbie question, but I used the code I found in Github, but it didnt worked.
I created a file named Menu.js with that content and another called Menu.css, also with the content you posted in Github. So I added this to index.html:
Ext.setup({
onReady: function() {
var viewport = Ext.Viewport;
// add extra css to viewport
Ext.Viewport.innerElement.addCls(‘viewport-inner’);
// add initial views
viewport.add([{
xtype: ‘mainmenu’
},{
xtype: ‘container’,
html: ‘Sencha Touch Example’,
padding: 10,
items: [{
xtype: ‘toolbar’,
docked: ‘top’,
title: ‘Sliding Menu’,
items: [{
iconCls: ‘home’,
handler: function() {
Ext.Viewport.child(‘mainmenu’).toggle();
}
}]
}]
}]);
}
});
What I am doing wrong? What else do I have to do?
Notice that I changed the ‘more’ icon to ‘home’ icon, so my fonts could read it. Thats all I did. Can you help me?
Hugs from Brazil!