Fork us on GitHub

Sidemenu On Top

The challenges of re-inventing the toolbar side menu
Sidemenu On Top

Sidemenu On Top

This feature is still undergoing development but I wanted to share the progress here so we can start getting bug reports and suggestions. One of the frequent requests for the side menu UI is to provide a way for it to render on top of the UI instead of shift the UI. The old side menu was written when the facebook app was the chief application that used that UI paradigm so it was built to match that approach.

The chief problem with the old side menu is that it was written prior to the Toolbar. As a result it was based on the Menu class which was designed in the age of feature phones. Many assumptions that were true back then no longer hold and as a result the side menu has a few elaborate hacks in place to make it feel fluid. When we started looking into the process of rendering the side menu on top we hit a wall.

There are multiple conflicting places in the code that position the side menu and do so in elaborate and unintuitive ways. The current side menu implementation is held back by legacy that makes even a seemingly simple change like this challenging. As a result we decided to take a completely different direction for the "on top" sidemenu.

A New Direction

When the original side menu was designed we didn’t have a layered pane and no InteractionDialog as a result the options for implementing the side menu were limited. When we ran into difficulty with implementing the "on top" mode in the same way as the regular side menu we decided to shift our focus into the Toolbar class. The on-top side menu is implemented entirely within the Toolbar.

The on-top side menu is based on the work we did for the permanent side menu and as a result some incompatibilities and different behaviors will occur when you use that approach. This side menu is placed into an interaction dialog and we use pointer event listeners to track the drag motion to expand and collapse it.

This means a few behaviors of the current side menu will be different:

  • Currently the on-top side menu appears below the Toolbar - We have a fix for this but it’s a bit "buggy" see the discussion below

  • On-top Side menu isn’t a separate form - the original side menu was a separate form. That means the existing UI was de-initialized & some subtle behaviors were different. The underlying UI would still be "live"

  • Shadow isn’t supported, however the underlying form is "darkened" gradually as we drag

  • Performance might not be as smooth at this time - we optimized the hell out of the old side menu, this isn’t as refined

  • The menu button is simply added to the left side - the old side menu had a special case we can’t use

  • Many of the theme constants aren’t supported yet, this is work in progress

This is how the new side menu looks in the kitchen sink:

We’d appreciate if you try the new side menu and let us know where you run into issues, to try is just add the following line to your init method:

Toolbar.setOnTopSideMenu(true);

In the future we will add a theme constant for this and might flip it to be the default.

Another Layered Pane

One of the problems with the new side menu is that it doesn’t cover the entire form due to the fact that InteractionDialog can’t render on the whole form. That is because the layered pane which the InteractionDialog depends on wraps the content pane and not the full Form.

That’s not a bad decision as the content pane is where we want most of our UI but there are special cases. Up until now our only option was glass pane but it’s too "low level". To solve this we added a new layer into Codename One with getFormLayeredPane which is semantically identical to getLayeredPane but is on top of the entire Form not just the content pane.

To prevent potential overhead we only add the form layered pane as needed based on user requests. Internally the form has a hidden border layout that you can’t normally access. It places the title area into its right place as well as the content pane etc. Adding another layer might have impacted compatibility or performance in a way that is too disruptive so we chose to use a rather creative approach…​

We added a new constraint to BorderLayout named OVERLAY which you can use as:

myBorderLayoutContainer.add(BorderLayout.OVERLAY, placeThisContainerOnTop);

This just places the component on top (or below) all of the elements within the Container so the overlay element will literally span the full size of the border layout regardless of all the other elements.

Z-ordering in Codename One is determined by the order of the elements so the last added element is on top by default

The InteractionDialog now has a special mode of working on the form layer which works for simple cases but has some rendering artifacts probably due to existing assumptions in the code regarding the Form which has some special cases. That’s why it isn’t enabled by default for the on-top side menu.

Ideally as we improve this and fix the issue we’ll flip the switch to use the form layered pane.

Finally

This is a bit of a big change, ideally this side menu should be the default but that probably won’t happen for 3.7 as the stability needs to improve. Once this is more stable we will probably flip the switch so developers can get the benefit of a more modern and simpler architecture facilitated by this new side menu.

Share this Post:

Posted by Shai Almog

Shai is the co-founder of Codename One. He's been a professional programmer for over 25 years. During that time he has worked with dozens of companies including Sun Microsystems.
For more follow Shai on Twitter & github.