Search code examples
mobilejavafxgridpanegluon

Gluon Mobile GridPane with percentages not working


I have a view with in the center a GridPane which fills the whole screen. The GridPane has percentages defined on all rows and all columns. On my Nexus 5X the layout works normal. When I install the app on a Zebra Scanner TC8000, which is an Android 4.4.3, the percentages are not respected. Instead roughly the upper 50% is shown and the rest disappears much like the screen is too small.

The resolution on the Zebra is much less of course, 480x800 vs 1080x1920 on the 5X but I expected that the components would scale down according to the percentages of the GridPane. Does anyone know what's going wrong.

Edit: I tried many different things and the best code I got atm is the code below. The problems this code has are: - The first row takes up 55% of the screen height instead of the 30% that is configured. - The components leave the screen in width by approximatly 50 - 100 pixels. If this one is solved the layout becomes acceptable.

<?xml version="1.0" encoding="UTF-8"?>

<?import com.gluonhq.charm.glisten.mvc.View?>
<?import javafx.geometry.Insets?>
<?import javafx.geometry.Rectangle2D?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<View fx:id="product" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.essers.pxl2016.scan.application.gluon.views.ProductPresenter">
    <padding>
        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
    </padding>
    <top>
        <HBox fx:id="buttonHBox" alignment="CENTER_LEFT" cacheShape="false" BorderPane.alignment="CENTER">
            <children>
                <Label fx:id="descriptionLabel">
                    <font>
                        <Font name="System Bold" size="15.0" />
                    </font>
                    <HBox.margin>
                        <Insets />
                    </HBox.margin>
                </Label>
                <Region HBox.hgrow="ALWAYS" />
                <Button fx:id="exitButton" mnemonicParsing="false" text="Exit">
                    <HBox.margin>
                        <Insets />
                    </HBox.margin>
                </Button>
            </children>
        </HBox>
    </top>
    <center>
        <GridPane>
            <columnConstraints>
                <ColumnConstraints fillWidth="false" percentWidth="100.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints percentHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints percentHeight="20.0" vgrow="SOMETIMES" />
                <RowConstraints percentHeight="50.0" vgrow="SOMETIMES" />
            </rowConstraints>
            <children>
                <GridPane hgap="4.0" vgap="4.0">
                    <columnConstraints>
                        <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" percentWidth="15.0" />
                        <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" percentWidth="15.0" />
                        <ColumnConstraints halignment="LEFT" hgrow="SOMETIMES" percentWidth="45.0" />
                        <ColumnConstraints halignment="CENTER" hgrow="SOMETIMES" percentWidth="25.0" />
                    </columnConstraints>
                    <rowConstraints>
                        <RowConstraints percentHeight="7.5" vgrow="SOMETIMES" />
                        <RowConstraints percentHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints percentHeight="5.0" vgrow="SOMETIMES" />
                        <RowConstraints percentHeight="7.5" vgrow="SOMETIMES" />
                        <RowConstraints percentHeight="45.0" valignment="CENTER" vgrow="ALWAYS" />
                        <RowConstraints percentHeight="5.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                    <children>
                        <VBox alignment="CENTER" spacing="5.0" GridPane.rowIndex="4">
                            <children>
                                <Button fx:id="plusButton" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#plusClicked" text="+" textAlignment="CENTER" VBox.vgrow="ALWAYS">
                                    <VBox.margin>
                                        <Insets />
                                    </VBox.margin>
                                </Button>
                                <Button fx:id="minButton" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#minClicked" text="-" textAlignment="CENTER" VBox.vgrow="ALWAYS">
                                    <VBox.margin>
                                        <Insets />
                                    </VBox.margin>
                                </Button>
                            </children>
                            <GridPane.margin>
                                <Insets />
                            </GridPane.margin>
                        </VBox>
                        <Label text="Count" textAlignment="CENTER" GridPane.columnIndex="1" GridPane.rowIndex="3">
                            <font>
                                <Font size="11.0" />
                            </font>
                        </Label>
                        <Label alignment="CENTER" contentDisplay="CENTER" nodeOrientation="LEFT_TO_RIGHT" text="Scanned barcode" textAlignment="CENTER" GridPane.columnIndex="2" GridPane.rowIndex="3">
                            <font>
                                <Font size="11.0" />
                            </font>
                            <GridPane.margin>
                                <Insets left="5.0" />
                            </GridPane.margin>
                        </Label>
                        <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#okClicked" text="OK" GridPane.columnIndex="3" GridPane.rowIndex="4">
                            <GridPane.margin>
                                <Insets />
                            </GridPane.margin>
                        </Button>
                        <Label text="Target">
                            <font>
                                <Font size="11.0" />
                            </font>
                        </Label>
                        <Label text="Scanned" GridPane.columnIndex="1">
                            <font>
                                <Font size="11.0" />
                            </font>
                        </Label>
                        <Label alignment="CENTER" text="Target barcode" GridPane.columnIndex="2">
                            <font>
                                <Font size="11.0" />
                            </font>
                            <padding>
                                <Insets left="5.0" />
                            </padding>
                        </Label>
                        <TextField fx:id="targetCountTextField" alignment="CENTER" disable="true" editable="false" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="5" GridPane.rowIndex="1" />
                        <TextField fx:id="countTextField" alignment="CENTER" maxHeight="1.7976931348623157E308" text="1" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="4" GridPane.rowSpan="2" GridPane.vgrow="ALWAYS" />
                        <TextField fx:id="targetBarcodeTextField" disable="true" editable="false" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="2" GridPane.rowIndex="1">
                            <opaqueInsets>
                                <Insets left="5.0" />
                            </opaqueInsets>
                        </TextField>
                        <TextField fx:id="scannedCountTextField" alignment="CENTER" disable="true" editable="false" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                        <TextField fx:id="scannedBarcodeTextField" maxHeight="1.7976931348623157E308" onKeyPressed="#handleKeyPress" GridPane.columnIndex="2" GridPane.rowIndex="4" GridPane.rowSpan="2">
                            <opaqueInsets>
                                <Insets left="5.0" />
                            </opaqueInsets>
                        </TextField>
                        <Button fx:id="skipButton" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#skipClicked" text="Skip" GridPane.columnIndex="3" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS" />
                    </children>
                </GridPane>
                <GridPane GridPane.rowIndex="1">
                    <columnConstraints>
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="0.0" percentWidth="29.0" prefWidth="0.0" />
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="31.0" prefWidth="100.0" />
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
                        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="25.0" prefWidth="100.0" />
                    </columnConstraints>
                    <rowConstraints>
                        <RowConstraints vgrow="SOMETIMES" />
                        <RowConstraints vgrow="SOMETIMES" />
                        <RowConstraints vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                    <children>
                        <Label text="Id:" />
                        <Label text="Location:" GridPane.rowIndex="1" />
                        <Label text="Description:" GridPane.rowIndex="2" />
                        <Label text="Comment:" GridPane.rowIndex="3" />
                        <Label text="Status:" GridPane.columnIndex="2" GridPane.rowIndex="1" />
                        <Label text="Unit:" GridPane.columnIndex="2" />
                        <Label fx:id="idLabel" GridPane.columnIndex="1" />
                        <Label fx:id="locationLabel" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                        <Label fx:id="longDescriptionLabel" wrapText="true" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="2" />
                        <Label fx:id="commentLabel" wrapText="true" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="3" />
                        <Label fx:id="statusLabel" GridPane.columnIndex="3" GridPane.rowIndex="1" />
                        <Label fx:id="unitLabel" GridPane.columnIndex="3" />
                    </children>
                </GridPane>
                <VBox GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
                    <children>
                        <Pane fx:id="pane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" VBox.vgrow="ALWAYS">
                            <children>
                                <StackPane fx:id="imagePane" alignment="TOP_LEFT" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
                                    <children>
                                        <ImageView fx:id="imageView" onMouseClicked="#imageClicked" pickOnBounds="true" preserveRatio="true" StackPane.alignment="CENTER">
                                            <viewport>
                                                <Rectangle2D />
                                            </viewport>
                                        </ImageView>
                                        <Button fx:id="videoButton" disable="true" mnemonicParsing="false" onAction="#videoButtonClicked" text="Video" visible="false" StackPane.alignment="TOP_RIGHT">
                                            <StackPane.margin>
                                                <Insets right="3.0" top="3.0" />
                                            </StackPane.margin>
                                        </Button>
                                    </children>
                                </StackPane>
                            </children>
                        </Pane>
                        <Label fx:id="figLabel" alignment="TOP_LEFT" />
                    </children>
                </VBox>
            </children>
        </GridPane>
    </center>
</View>

Solution

  • You can reproduce the issue if you run your app on Desktop, and set the stage dimensions to 320x600:

    @Override
    public void postInit(Scene scene) {
        scene.getWindow().setWidth(320);
        scene.getWindow().setHeight(600);
    }
    

    View 370

    Using ScenicView you'll notice that the view has 370 px width, because the minimum width for the top inner grid is 360 px.

    While you haven't set any minimum value for any control, you can see that the styled buttons don't resize down properly, as the minimum width is set by css.

    Try adding this to remove their minimum width value:

    .view {
    }
    
    .button {
        -fx-min-width: 10;
    }
    

    Now the view should be within the bound of the mobile screen:

    View 320