javajavafxgluon-mobile

ComboBox makes selection with touch events difficult


This class creates a view with a ChoiceBox, ComboBox settings pane with a ComboBox:

import javafx.collections.FXCollections;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.control.Toast;
import com.gluonhq.charm.glisten.mvc.View;

public class OptionsView extends View {

    public OptionsView() {
        var choicebox = new ChoiceBox<>(FXCollections.observableArrayList("aaav", "bvvv", "cssss"));
        choicebox.getSelectionModel().select(0);
        choicebox.showingProperty().addListener((obs, ov, nv) -> System.out.println("ChoiceBox On showing: " + nv));
        choicebox.setOnAction(e -> System.out.println("ChoiceBox On action: " + e));
        choicebox.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> System.out.println("ChoiceBox On selection: " + nv));
        choicebox.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> new Toast(nv + " selected").show());

        var combobox = new ComboBox<>(FXCollections.observableArrayList("aaav", "bvvv", "cssss"));
        combobox.getSelectionModel().select(0);
        combobox.showingProperty().addListener((obs, ov, nv) -> System.out.println("ComboBox On showing: " + nv));
        combobox.setOnAction(e -> System.out.println("ComboBox On action: " + e));
        combobox.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> System.out.println("ComboBox On selection: " + nv));
        combobox.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> new Toast(nv + " selected").show());

        setTop(new HBox(30, combobox, choicebox));

        var bigListView = new ListView<>(FXCollections.observableArrayList("AAAAA", "FFFFF", "GGGGG"));
        bigListView.setCellFactory(c -> createListCell(26));
        bigListView.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> new Toast(nv + " selected").show());

        var smallListView = new ListView<>(FXCollections.observableArrayList("aaaaa", "fffff", "ggggg"));
        smallListView.setCellFactory(c -> createListCell(14));
        smallListView.getSelectionModel().selectedItemProperty().addListener((obs, ov, nv) -> new Toast(nv + " selected").show());

        setCenter(new VBox(bigListView, smallListView));
    }

    private static ListCell<String> createListCell(double fontSize) {
        var cell = new ListCell<String>() {
            {
                textProperty().bind(itemProperty());
                setFont(Font.font(fontSize));
                setOnTouchPressed(e -> new Toast(getText() + " touched").show());
                setOnMouseClicked(e -> new Toast(getText() + " clicked").show());
            }
        };
        return cell;
    }

    @Override
    protected void updateAppBar(AppBar appBar) {
        appBar.setTitleText("Options");
    }
}

On Android, when trying to select (with touch events) from the ChoiceBox, selection works fine. However, trying to select from the ComboBoxs does not work properly. The user choice is usually ignored - the dropdown menu closes without a new selection, and only after several attempts it selects another option.

Using

    <maven-compiler-plugin-version>3.10.1</maven-compiler-plugin-version>
    <javafx-maven-plugin-version>0.0.8</javafx-maven-plugin-version>
    <gluonfx-maven-plugin-version>1.0.15</gluonfx-maven-plugin-version>

    <java-version>17</java-version>
    <javafx-version>19</javafx-version>
    <charm-version>6.2.2</charm-version>
    <attach-version>4.0.15</attach-version>

with javafxStaticSdkVersion 19 and using graalvm-svm-java17-linux-gluon-22.1.0.1-Final.

This occurred with charm 6.1 as well.

When running on desktop, selection with the mouse works fine.


Solution

  • As explained in the comments by @José Pereda, the problem comes from this part of code in JavaFX: https://github.com/openjdk/jfx/blob/master/modules/javafx.graphics/src/main/java/com/sun/glass/ui/monocle/TouchInput.java#L44.

    This value defines the touch radius for that differentiates touch events from scroll events (hysteresis).

    If the touch radius is too small and the device's screen is too sensible, the still gestures can be changed into scroll/other gestures instead of click events.
    A small value on Android allows scrolling after a finger tiny movement, for instance, but if it is too small a single finger tap on a very sensitive device may lead into many touch events on different locations (as these don't get filtered out), which could be interpreted as a scroll event instead of a click event

    Setting System.setProperty("monocle.input.touchRadius", "2"); in main solves the issue.