0

I am using HelloFx project from gluon client samples. And used Java 11.0.10 withgluon client plugin 0.1.41 to build APK.

I've added default javafx TextField(javafx.scene.control.TextField) and PasswordField(javafx.scene.control.PasswordField).

When I run the app directly in desktop (linux), I was able to type inside the password field and the 'bullets' appear properly. hellofx-password-field-bullets issue

But when I built APK and tested in an android device, the bullets are not rendered correctly, they are shown as boxes. enter image description here

So, I've created a new skin to change the 'mask character' of password field to \u2022 as shown in this stackoverflow answer. In desktop, it worked with no issues. In android device the characters are properly shown as bullets but when I tap on that field the keyboard either doesn't show up or hides if it is already showing up.

Here's the PasswordFieldSkin.java:

public class PasswordFieldSkin extends TextFieldSkin {
    public static final char BULLET = '\u2022';

    public PasswordFieldSkin(PasswordField passwordField) {
        super(passwordField);
    }

    @Override
    protected String maskText(String txt) {
        TextField field = getSkinnable();
        int n = field.getLength();
        StringBuilder passwordBuilder = new StringBuilder(n);

        for (int i = 0; i < n; i++) {
            passwordBuilder.append(BULLET);
        }

        return passwordBuilder.toString();
    }
}

Here's the pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>hellofx</groupId>
    <artifactId>hellofx</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>HelloFX</name>

    <properties>
        <main.class>hellofx.HelloFX</main.class>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>11</maven.compiler.release>
        <javafx.version>15.0.1</javafx.version>
        <javafx.maven.plugin.version>0.0.6</javafx.maven.plugin.version>
        <client.maven.plugin.version>0.1.41</client.maven.plugin.version>
        <charm.version>6.0.6</charm.version>
        <glisten.afterburner.version>2.0.5</glisten.afterburner.version>
        <attach.version>4.0.10</attach.version>
        <connect.version>2.0.1</connect.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>

        <!-- Added jackson dependency here -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.1</version>
        </dependency>
        <!-- Added JavaTime data type -->
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>2.12.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>

            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>${javafx.maven.plugin.version}</version>
                <configuration>
                    <mainClass>${main.class}</mainClass>
                </configuration>
            </plugin>

            <plugin>
                <groupId>com.gluonhq</groupId>
                <artifactId>client-maven-plugin</artifactId>
                <version>${client.maven.plugin.version}</version>
                <configuration>
                     <target>${client.target}</target>
                     <mainClass>${main.class}</mainClass>
                     <reflectionList>
                        <list>hellofx.Person</list>
                        <list>com.fasterxml.jackson.core.JsonFactory</list>
                     </reflectionList>
                     <nativeImageArgs>
                        <nativeImageArg>--allow-incomplete-classpath</nativeImageArg>
                     </nativeImageArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>desktop</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <client.target>host</client.target>
            </properties>
        </profile>
        <profile>
            <id>ios</id>
            <properties>
                <client.target>ios</client.target>
            </properties>
        </profile>
        <profile>
            <id>android</id>
            <properties>
                <client.target>android</client.target>
            </properties>
        </profile>
    </profiles>

</project>

And finally, here's the main method:

public class HelloFX extends Application {

    private Label parseStatusLabel = new Label("");
    
    private String serializedString = null;

    public void start(Stage stage) {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        Label label = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");

        ImageView imageView = new ImageView(new Image(HelloFX.class.getResourceAsStream("/hellofx/openduke.png")));
        imageView.setFitHeight(200);
        imageView.setPreserveRatio(true);

        TextField textField = new TextField();
        textField.setText("Username");
        PasswordField passwordField = new PasswordField();
        passwordField.setSkin(new PasswordFieldSkin(passwordField));
        passwordField.setText("Password");

        VBox root = new VBox(30, imageView, label, textField, passwordField, parseStatusLabel);
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 640, 480);
        scene.getStylesheets().add(HelloFX.class.getResource("styles.css").toExternalForm());
        stage.setScene(scene);
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

How to solve this issue?

  • 2
    The TextField on Android uses its own [TextFieldSkinAndroid](https://github.com/openjdk/jfx/blob/master/modules/javafx.controls/src/android/java/javafx/scene/control/skin/TextFieldSkinAndroid.java), so you can't override PasswordFieldSkin, without losing that skin that manages the keyboard. The good news is that this is a known issue and was [fixed](https://bugs.openjdk.java.net/browse/JDK-8269026) recently, and it should be available in the next version of the plugin (1.0.3). – José Pereda Jul 01 '21 at 10:30
  • Thanks for the quick reply. Good to know that it's already fixed. – Mani kandan Jul 01 '21 at 10:44
  • In theory, you can already test plugin 1.0.3-SNAPSHOT, it requires this repo: ` sonatypee http://oss.sonatype.org/content/repositories/snapshots/ `, and make sure you "migrate" to the latest version of the rebranded `gluonfx` plugin: https://docs.gluonhq.com/#_upgrading_from_previous_versions – José Pereda Jul 01 '21 at 11:53

0 Answers0