A Java™ developer who is used to developing GUIs with Swing and who is now trying to get into Android might be surprised: Java is not the same on Android.
The fact that Java is different on Android has been discussed in some blogs on the net already, so I just sum it up to this: Android applications can be written by any developer who knows the Java programming language. But the number of available runtime classes on Android is different: there are fewer classes in Android regarding package
java.* compared to Sun Java Standard or Micro Edition. The most surprising fact for a Java GUI developer might be that there is no Swing on Android.
This article demonstrates some aspects of how a simple Java Swing application with a nice Look and Feel was transferred to Android. The main focus is set on how to write the application with the Android SDK and the styling and theming abilities of Android.
Our example application is a contact manager that is styled with a Java Swing Look And Feel from Centigrade running on the Cezanne Look and Feel Engine. The application consists of three screens: a contact list, a contact details overview screen and a screen for editing the contact’s detail information. The option for adding or removing contacts has been omitted on purpose for the example.
"Contact Overview" screen of the demo application
The contact list is kept within a scroll pane, so further contacts can be seen by scrolling down. When the user double-clicks an entry in the "Contact Overview" screen, he gets to the "Contact Details" screen.
"Contact Details" screen of the demo application
On the "Contact Details" screen there is a navigation toolbar on the bottom. The toolbar provides buttons with actions that allow the user to either go back to the contact list or to proceed to a screen that allows him to see and change all the contact’s details.
"Edit Contact" screen of the demo application
On the "Edit Contact" screen the user can edit detailed information of the contact and either submit or cancel changes he has made. Both actions bring him back to the "Contact Details" screen.
The following section shows how the GUI of the Swing prototype was implemented for Android with Eclipse™. However, it has to be noted first that the target Android platform was chosen to be 1.6 because at the time when I was implementing this it was still spread widely on phones out there.
As there is no Swing on Android, not much of a Swing application can be reused on Android. The whole GUI code of the Swing prototype has to be re-implemented, obviously. Only the code providing the data for the contacts and the contact bean as the central application model are reused.
For the GUI of an Android application the documentation encourages to prefer XML over Java for reasons of separating the application’s presentation from the application logic. This sounds reasonable as this can help facilitating collaboration between designers and developers similarly as discussed in David’s blog post.
An additional advantage of choosing XML over Java for Android GUIs is the built-in Eclipse editor that allows a preview of the layout. This is a very helpful and nice feature on the one hand. On the other hand, I found myself editing those XML files by hand still a lot (as find/replace or copy/paste made me a lot quicker) and this can – for complex screens – soon become an adventure similar to finding a needle in a haystack.
In Android’s GUI classes there are a lot of GUI components that are similar to Swing. It looks like there is a view class for everything a Swing developer works with day-to-day:
JTextComponent and so forth.
The comparison of the layout concept of container components Android’s GUI classes and Swing was surprising. In Swing, all components inheriting from class
Container have a layout manager that – as the name suggests – explicitly handles the process of laying out its child components.
LayoutManager is a stand-alone interface, not inheriting any view aspects. That way, the layout process is clearly separated from the view component.
This concept is not used like that on Android’s GUI classes. Let’s take Android’s
LinearLayout – an easy-to-understand and easy-to-use layout. It is heavily used to recreate the Swing Contact Manager Sample Application on Android. As this class is residing in the
android.widget package this can give the impression that it actually is a widget. Moreover,
LinearLayout inherits from
ViewGroup which in turn extends
View. This proves that
LinearLayout in fact is a view. As Swing developer, one can at first be confused that a layout class like
LinearLayout is part of the view class hierarchy, especially when seeing the class name for the first time.
Nevertheless, together with these and other information I was able to build the whole GUI of the sample Application on Android. Layout was completely done by stacking
LinearLayouts on top of each other and using
EditTexts as GUI components. I chose XML for the GUI and layout part of the application, while I kept the application logic in Java code – as suggested by Google.
Outline of the layout of a screen in Eclipse
The above screenshot shows a part of the view tree in the Eclipse outline of the "Edit Contact" screen. You can clearly see how the GUI is composed and it is also possible to edit properties in the second tab. When an entry in the view tree is selected it also gets highlighted in the layout preview with a red border as can be seen in the following screenshot. It shows the layout preview of the "Edit Contact" screen in Eclipse.
Layout preview in Eclipse
After creating all the screens like that and after implementing the logic in Java the application finally looks and behaves like the Swing prototype – but it is still styled with the default Android theme. Styling of the Android application will be dealt with in the next section.
Styles and Themes
The Swing prototype application that is the base for this article is styled with a Java Swing Look and Feel designed by Centigrade and driven by the Cezanne Look and Feel Engine. This section discusses to what extend the goal has been reached to style the Android application so that it looks like the Swing application.
When starting the work on the theme conversion, one of the first things to be found out is how styling works for Android. The Android developer web site is a good starting point in that respect. But, what was written there in the section "Applying Styles and Themes" at the time when I was performing the implementation, was only the tip of the iceberg. There was a rather short explanation on how to define styles and themes. Unfortunately, the example in the section on themes did not work for me and a hint on where to find more information was lacking. Fortunately, this article on Android themes and styles helped. Only its section "So what can I style, and from what can I inherit?" left a bit to be desired. The author proposed having a look in class
R.styleable. This satisfied me at first. But then I was facing the absence of this class in my workspace. Neither class
R of the android runtime nor the one generated in my project contained the
styleable class I was desperately looking for. I finally found it in the local Reference Documentation as part of the Android SDK. While looking for this class I also found the following statement on the online release notes page of Android’s web pages: "android.R.styleable class and its fields were removed from the public API…".
At this point I thought it would be a better idea to have a look into Android SDK folder for XML sources. And indeed there it was, all information in xml files: styles.xml, themes.xml, colors.xml and so on. Seeing a light at the end of the tunnel, it was now possible to find out what can be styled by examining the mentioned files. In the meantime, the documentation on Android’s web page has been updated and contains much more useful information, I wish had it when I was implementing this.
One of the most important steps was to bring the image assets to Android. The Java Swing Look and Feel in the Swing application uses PNG slices and the Cezanne Look and Feel engine from Centigrade supports 9-Slice-Scaling for background images of components. This is also supported by Android’s theming facility but under a different name: 9-Patch-Images. This is basically the same idea as in Cezanne: an image will be subdivided into 9 areas where some of the areas are stretched while others remain fixed in size. In Cezanne, these areas are defined by providing insets for each top, left, bottom and right. In Android, the images already contain the information in an additional one-pixel border around the image, so this information is kept within the image itself, as you can see on the Android developer page’s section about NinePatchDrawable.
Now, let’s see how Android supports setting background styles. This can be seen in the XML code snippet below.
<!-- more properties -->
This sets an image as background for a button in the toolbar. The statement starting with
@drawable in this case directly references an image resource in the drawable folder of the Eclipse project.
The next important question now was how to tell Android that a button will look differently for the respective GUI component states such as
pressed, etc. Some digging in the Android XML source files revealed that this can be achieved by creating a drawable XML file that uses the
selector element and declares the corresponding real image resources (in this case 9-Patch-Images) for each state:
<!-- more state declarations -->
Instead of referencing an image directly in the
ToolbarButtonStyle code sample further above, this XML is saved with the name
button_toolbar.xml into the drawable folder of the eclipse project and the
ToolbarButtonStyle will show different images for different button states. The
selector element is a nice and flexible concept of indirection, which provides the necessary degrees of freedom for this use case.
One more example where this concept came in handy was the declaration of the background pattern, which is used throughout the application. The pattern is created as a texture that should be repeated. Setting the background image naively by referencing the image directly resulted in the android application showing the background painted as a stretched version. Again, it was an XML file as drawable that saved the day. With the bitmap XML element the repeat-effect for the background image could be implemented like this:
Please note the
tileMode attribute, where the value
repeat has been set. This XML has to be saved in the drawable folder and can then be used instead of an image file.
Going on like this, in the end it was possible to transfer all styles from the Cezanne-powered Java Swing Look and Feel to Android.
Note that the scrollbar’s style is different on Android, the visual drag indicator in the middle has been left out as well as the arrow buttons. The reason for this is that in contrast to other mobile platforms – like e.g. Windows Mobile – the scrollbar thumb can’t be touched and dragged on Android. This is a pure visual indicator there and it has no interactional function.
We have seen that Android uses Java as language for writing applications, but it is not Sun Java (or rather: Oracle™ Java?), neither Standard Edition nor Micro Edition especially when it comes to GUI classes. In addition, it uses its own virtual machine called Dalvik VM. So, as a developer with a background in Sun’s Java and Swing this means being confronted with new classes and maybe even new or different concepts. But this is a doable task. Describing the GUI of an application via XML is similar to what Microsoft™ does with XAML and surely has advantages as well as disadvantages.
Regarding styling capabilities, Android seems to support styling of a lot of widgets (and even of Layouts) – if not all. The Nine-Patch-Drawables and the very nice indirection concepts of drawables in general are really neat and allow creating stunning themes that can visually catch up with a Java Swing Look and Feel.
Oracle is a registered trademark of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.
Microsoft is a registered trademark of Microsoft Corporation in the United States and/or other countries.
Eclipse is a trademark of Eclipse Foundation, Inc.
Android is a trademark of Google Inc. Use of this trademark is subject to Google Permissions.