In this special case, an image and a text should next to each other on a desktop. In a smaller (mobile) version the text should be placed under the image. You can find the question at stackoverflow, too.
I want to start with a first look at how the solution should look like. The following picture shows the described layout on a big and on a small screen:
Let’s discuss several approaches that we can use to create this behavior.
Switch between HBox and VBox
One suggested solution is to switch between an HBox and a VBox at runtime. This means that on a big screen you will see the image and text wrapped in an HBox and when the size becomes smaller the HBox will be replaced by a VBox. By doing so we need to discuss if we want to reuse the text and image component in both layouts or create a separate instance for each layout. Here I think that recycling of the components is a good idea. If you use 2 instances you need to sync them. By using the JavaFX property API this isn’t as hard as it sounds in the first moment but it can still create some errors. So let’s have a look at a code snippet that creates the basic view:
When running this example the view will be shown with the text and image next to each other:
As a next step we want to refactor the code by using a VBox:
In this example the text will be displayed under the image as it should look on small devices:
As a last step we want to modify the code and create an application that will change it’s layout dynamically:
In this first try, the mainPane contains the hBox or the vBox depending on the width of the scene. To do so a lister is attached to the width property. In addition, the children of the vBox and hBox will be cleared and the text and image will be attached to the currently visible panel. As you can see in this video the view already behaves as it should:
There are still some ugly parts in the code. As you might have noticed the listener will be called for each repaint of our stage. therefore nodes will be replaced and added to the scene graph all the time. Here we can use the JavaFX binding API to create a more performant binding. Here is the code snippet that shows the changed code:
Now the scene graph will only be changed if the size will become greater or smaller than 600 pixels.
I think this is a valid solution for the given problem and we can create a responsive behavior this way. But I think that it's not the perfect solution and therefore I will show another and easier approach the next days.
Hendrik Ebbers is a co-founder of Karakun AG and lives in Dortmund, Germany. He is the founder and leader of the Java User Group Dortmund and gives talks and presentations in user groups and conferences. His JavaFX book "Mastering JavaFX 8 Controls" was released 2014 by Oracle press. Hendrik is JavaOne Rockstar, JSR expert group member and Java Champion.