Mobile web has brought up a trend that is called responsive web design (RWD). This commonly refers to a technique where the same HTML file is displayed in a bit of a varying manner, based on the screen size of the end user. This is achieved by some carefully crafted DOM structure and modern CSS rules.
In Vaadin 7.2 we introduced a new helper class called Responsive. With it one can easily apply this technique within Vaadin applications and layouts. But if you don’t excel with modern CSS or just don’t like to use it, similar outcome can be achieved in plain Java as well. This has actually been possible long before the RWD term was even coined and it is by no means a new thing for Vaadin and GWT developers. Some have come up with terms like RESS for this kind of technique, but from the end users’ point of view, the result is pretty much the same.
As we can deliver a different DOM structure for various devices, this method may actually prove to be more flexible and lighter (read: faster) for mobile devices. Not just selecting optimal components or layouts for various devices, but we can actually control the amount of content we give for the browser to process. Based on the screen size, or even based on the browser software, you can select the optimal amount of data from your backend.
Because of the strong RWD trend, this plain Java method hasn't been that much discussed lately. Thus, I decided to present you a couple of code snippets for inspiration and, naturally, an acronym for it, namely RWD-PJ – Responsive Web Design in Plain Java :-)
Note that although the methods I present here are written with Vaadin’s server side components, the concepts apply just as well for the client side (GWT) world.
Method 1: Layout mode selection
The chosen layout in RWD most often depends on the width of the available space for the web content. In Vaadin this detail can easily be detected via the Page object. The following code snippet will get the widget and categorize it into a meaningful enumeration value.
public LayoutMode getLayoutMode() { int width = Page.getCurrent().getBrowserWindowWidth(); if (width < 800) { return LayoutMode.SMALL; } else { return LayoutMode.DESKTOP; } }
In this example I only use two modes for simplicity, but naturally you can use any number of modes you want. The actual usage of this detail is trivial. You may use basic if-else clauses or even switch-case structures if you have lots of modes.
In my example app I’m just using this value to select from two different navigation options. I bet you have more complex needs in real projects, but they should be pretty easy to implement - and cheap to maintain.
Method 2: Layout logic without boundaries
Another option is not to classify your screen sizes to any group at all. If you are a developer, you must be able to write some methods to do some basic math for optimal layout setup.
Consider you have a webshop app and in its product listing each product slot scales horizontally otherwise, but needs at least 300 pixels to look sane. You probably want to fill the whole screen with as many products as possible. Can you imagine something simpler than a Java method to describe this logic?
private int getOptimalColumnCount() { return getMainAreaWidth() / MIN_SLOT_WIDTH; }
private int getMainAreaWidth() { int availableWidth = Page.getCurrent().getBrowserWindowWidth(); if (getLayoutMode() == LayoutMode.DESKTOP) { // in desktop mode menu is on the left side of main content area availableWidth -= MENU_WIDTH; } return availableWidth; }
It will be pretty easy to figure out what that does when you need to return to your project for some maintenance after 5 years in some other projects. As this is by no means a competition to write compact code, I already split the logic for better readability and reusability.
Let’s assume the app also has a paging mechanism for your products. Similar simple calculations can also be used to choose the optimal amount of items for this specific client. You probably know or can define the height of one cell. Then just use the height of the screen and reuse the column amount from the previous example. Low end mobile devices no more need to choke under dozens of items, an amount that might be optimal for a desktop browser.
Bonus: Implementing the “demo features”
If some responsive design guru has actually read this far, and on the way tried out the examples in action, I bet he/she is about to comment that "This doesn't change the layout on the fly!". To support reasonable software development efforts, I'd like to answer "So what, when have you actually resized your browser window, when not testing your responsive rules in CSS?".
But to impress your boss with your responsive layouts and, well, also to support orientation changes in small mobile devices, you can hook to WindowResizeEvents:
getPage().addBrowserWindowResizeListener(e -> { // rebuild layout if necessary if (currentMode != getLayoutMode()) { reLayout(); } });
This code will automatically cause your layout routines to be executed, when your window size has changed from a threshold to another.
When should I use this approach?
Selecting tools and methods in the software business is never easy. In addition to technical realities, things like available skills and budget always affect your optimal solution. You can do lots of tricks with CSS and I’d definitely use simple RWD for new small to medium sized websites. In web applications and large website projects, I’d definitely make some decisions also before building the final DOM, most likely adding server side logic, and leave CSS to fine tuning the look and feel. Afterall, the amount of data sent over the wire is escpecially important on mobile devices.
I also wanted to remind you that only the result matters. If technology X creates a hype with some method, it doesn't make your tool worse - as long as you can achieve the same result. Consider if it makes a difference to the end user experience or your productivity.