Fork us on GitHub

Fractional Padding/Margin, Rounded Border, Ripple, Caps, Google Connect

A big list of features from the past week
Fractional Padding/Margin, Rounded Border, Ripple, Caps, Google Connect

Fractional Padding/Margin, Rounded Border, Ripple, Caps, Google Connect

We’ve been very busy the past few weeks despite the summer time but August is always problematic, I will personally take some time off from the blog next week and near the end of August. To allow that I want to clear my table from a lot of the features that went into Codename One over the past couple of weeks and didn’t get sufficient or any documentation…​

I wrote about some of these features before in the pixel perfect posts but I glossed over them. Some of the other features I didn’t cover at all!

Google Plus is Dead

Even when we wrote the blog posts detailing google plus login we new the end was near for that social network…​

Google has pretty much ended support for the old Google+ login API’s and Steve migrated our existing Google+ support to use standard Google account connect. The cool thing is that the integration should now be MUCH easier and can be summed up with:

  • Go to the Google Developer Portal

  • Follow the steps to create an App

  • Enable Google Sign-In

  • Download the google-services.json file into your project’s native/android directory

  • Download the GoogleService-Info.plist file into your project’s native/ios directory

This is the super short version…​ Steve updated the developer guide section on Google Cconnect with a longer more detailed explanation of the steps.

Fractional Padding/Margin

This is a pretty big feature, currently the only way you can use this is by compiling your own version of the Codename One Designer but it will be around with plugin update 3.7.3 (we don’t have an ETA for that yet but I hope it won’t be too long).

This essentially means you would be able to use fractions to define padding and margin in the designer UI:

Fractions in margin
Figure 1. Fractions in margin

This won’t work for pixels, it will get rounded down. But it should work great for millimeters where 1mm often proved to be too much in newer devices.

The reason we didn’t have that around sooner is that it requires a deep change to the resource file format which is always a painful nuanced process. We bundled this with another big change to the file format…​

Rethinking Round Rect

We created Border in the LWUIT days and it grew very old. The goals it set out to accomplish were radically different from the ones we have today which is why we created RoundBorder when we needed something more expressive.

RoundBorder works great for round and pill shapes but the classic square with rounded corners is still only available in the Border class. Normally, this would be enough but there is a lot of nuance we wanted to introduce to that API and a lot that we learned from the RoundBorder. So we created a new class RoundRectBorder which allows you to create a round border that’s more refined. Here I adapted the original RoundBorder sample to work with RoundRect:

Form hi = new Form("RoundRect", new BorderLayout(BorderLayout.CENTER_BEHAVIOR_CENTER));

Button ok = new Button("OK");
Button cancel = new Button("Cancel");

Label loginLabel = new Label("Login", "Container");
loginLabel.getAllStyles().setAlignment(Component.CENTER);

Label passwordLabel = new Label("Password", "Container");
passwordLabel.getAllStyles().setAlignment(Component.CENTER);

TextField login = new TextField("", "Login", 20, TextArea.ANY);
TextField password = new TextField("", "Password", 20, TextArea.PASSWORD);
Style loginStyle = login.getAllStyles();
Stroke borderStroke = new Stroke(2, Stroke.CAP_SQUARE, Stroke.JOIN_MITER, 1);
loginStyle.setBorder(RoundRectBorder.create().
        strokeColor(0).
        strokeOpacity(120).
        stroke(borderStroke));
loginStyle.setBgColor(0xffffff);
loginStyle.setBgTransparency(255);
loginStyle.setMarginUnit(Style.UNIT_TYPE_DIPS);
loginStyle.setMargin(Component.BOTTOM, 3);
Style passwordStyle = password.getAllStyles();
passwordStyle.setBorder(RoundRectBorder.create().
        strokeColor(0).
        strokeOpacity(120).
        stroke(borderStroke));
passwordStyle.setBgColor(0xffffff);
passwordStyle.setBgTransparency(255);


Container box = BoxLayout.encloseY(
        loginLabel,
        login,
        passwordLabel,
        password,
            GridLayout.encloseIn(2, cancel, ok));

Button closeButton = new Button();
Style closeStyle = closeButton.getAllStyles();
closeStyle.setFgColor(0xffffff);
closeStyle.setBgTransparency(0);
closeStyle.setPaddingUnit(Style.UNIT_TYPE_DIPS);
closeStyle.setPadding(3, 3, 3, 3);
closeStyle.setBorder(RoundBorder.create().shadowOpacity(100));
FontImage.setMaterialIcon(closeButton, FontImage.MATERIAL_CLOSE);

Container layers = LayeredLayout.encloseIn(box, FlowLayout.encloseRight(closeButton));
Style boxStyle = box.getUnselectedStyle();
boxStyle.setBgTransparency(255);
boxStyle.setBgColor(0xeeeeee);
boxStyle.setMarginUnit(Style.UNIT_TYPE_DIPS);
boxStyle.setPaddingUnit(Style.UNIT_TYPE_DIPS);
boxStyle.setMargin(4, 3, 3, 3);
boxStyle.setPadding(2, 2, 2, 2);

hi.add(BorderLayout.CENTER, layers);

hi.show();
Round rect sample
Figure 2. Round rect sample

There are several things we learned from doing the RoundBorder that we applied and did differently in RoundRectBorder:

  • We use the UIID for the background color that just makes sense. We didn’t do the same for the stroke color/foreground color though. The background should now behave nicely including gradients and images!

  • We use millimeters where it makes sense, so a stroke can be in pixels since a 1 or 2 pixel stoke is something you might need but corner radius is always in millimeters as pixels just don’t fit here

This can also be customized via the designer tool which is another reason we had to change the resource file format:

New rounded rectangle UI in the designer tool
Figure 3. New rounded rectangle UI in the designer tool

Ripple Effect

The ripple effect is an Android effect that occurs when you press and hold a button. It ripples slightly.

It’s actually pretty nice and assuring that your touch was intercepted. This effect is implemented in the component level but at the moment it was only turned on for Button. Moving forward this will probably be enabled for MultiButton, SpanButton and other component types.

Every component has a ripple effect flag now that you can check and toggle via isRippleEffect() and setRippleEffect(boolean). In buttons that flag is set from the default state which you can tune via the theme constant buttonRippleBool or via the Button.setButtonRippleEffectDefault(boolean) method.

When a component is pressed and it has the ripple effect we keep painting it until it’s released. During that time we draw a translucent black color on top as a growing circle until it fills up the available space. You can customize the behavior of this painting by overriding paintRippleOverlay(Graphics g, int x, int y, int position). I wouldn’t recommend doing that unless you are going for a completely unique application look.

Button Caps

One of the more controversial changes we made was to upcase all the button text by default for Android. You can disable that behavior by using the theme constant capsButtonTextBool and set it to false or invoking Button.setCapsTextDefault(false).

Android buttons should be upper case but iOS should have correct casing. This is very obvious when looking at iOS/Android UI’s critically. If you want to leave the global behavior but have case correctness for one individual button you can do this by invoking Button.setCapsText(boolean).

In order to reduce the impact of this behavior we didn’t apply it to every Button in existence even when it’s turned on. This only applies to Dialog buttons and buttons with the UIID’s Button or RaisedButton. That means that if you have a custom button UIID you will need to explicitly call setCapsText(Button.isCapsTextDefault()) to force this feature on for that Button.

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.