Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Making Mobile Write Once Run Anywhere Gorgeous

DZone's Guide to

Making Mobile Write Once Run Anywhere Gorgeous

One challenge of Write Once Run Anywhere tools is getting them to look native. Take a look at one way to make the UI look great in both iOS and Android.

· Mobile Zone ·
Free Resource

Write Once Run Anywhere tools get a lot of flack for not looking native enough, and honestly, we haven’t done enough to fix that reputation. Tools are only now starting to mature as the rate of progress in the mobile industry is slowing down and giving us room to catch up.

The fact that Android and iOS are far more similar today than they were when we launched (Android 2.x/iOS 4 days) makes this even easier…

But instead of mincing words, let's mince pictures; this is a screenshot of Text Input in Codename One 3.7 in Android:

This is how the same UI looks now:

It’s unclear from the image, but the label “floats” into place when there is no text. We even support the cool error messages from material design and the animation effect when the hint animates into a label:
Material style errors with no text, so the label appears as a hint.
Material style errors with text in place showing that the label gets the right red color. You might think this would look out of place in iOS, but this is how this exact same code looks on iOS
I think we can improve the iOS version a bit, but for this release, we put our focus on Android more, as we felt it languished too far behind.

The “Magical” Code

Producing the UI above is remarkably easy in Codename One and requires only this small block of code:

TextModeLayout tl = new TextModeLayout(3, 2);
Form f = new Form("Pixel Perfect", tl);

TextComponent title = new TextComponent().label("Title");
TextComponent price = new TextComponent().label("Price");
TextComponent location = new TextComponent().label("Location");
PickerComponent date = PickerComponent.createDate(new Date()).label("Date");
TextComponent description = new TextComponent().label("Description").multiline(true);

Validator val = new Validator();
val.addConstraint(title, new LengthConstraint(2));
val.addConstraint(price, new NumericConstraint(true));

f.add(tl.createConstraint().widthPercentage(60), title);
f.add(tl.createConstraint().widthPercentage(40), date);
f.add(location);
f.add(price);
f.add(tl.createConstraint().horizontalSpan(2), description);
f.setEditOnShow(title.getField());

f.show();

As you can see, the code is pretty simple; we just define the text components and their constraints for the validation code. Everything else, including the animations and OS-specific behavior, is automatic, and that’s pretty cool.

We Need Your Help!

We made a lot of improvements to the look of Codename One in the 3.8 release, and it’s going to remain a focus in the coming 4.0 release, too. One of the main difficulties for us is deciding what’s important and the level of detail that we need to get into in terms of look and feel. For that, we need your help. We need you to file issues in the issue tracker, but not “broad issues” like “implement material design.”

***

If you want to learn more about this I wrote quite a few blog posts in the pixel perfect series on our website that go very deep into the technical details. I explain in far more detail what I had to go through in order to achieve these effects and why.

We need issues that point narrow achievable effects or behaviors that we get wrong so we can focus on fixing smaller things as we move the whole platform forward. It’s mostly a matter of resources and priorities and if people just complain that “WORA doesn’t look good” that doesn’t help… We need the complaint but we need it to be more specific and ideally include screenshots from Codename One vs. a native UI so we can align against an anchor.

Topics:
ui design ,wora ,ios ,android ,open source ,mobile ,mobile app development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}