Open ctoabidmaqbool opened 1 year ago
This also depends on the index.html file, and how the Stage/Scene/Root is set up. So I guess I would need a sample application. And a better description of what's actually happening. Maybe then it will be immediately clear whats happening.
Hi @FlorianKirmaier ! I want to design different front-end GUI depending upon the orientation of devices, e.g. landscape or portrait. Also w.r.t different width like CSS media queries.
I am not sure, how can I achieve them in JPro?
The main thing is somehow I can add listener to main viewport area's size of web! But how to achieve this in JPro Web?
The Node of your Page, should, by default be layout to the size (width/height) of the WebSite.
(You might want to set it to fullscreen: .filter(Filters.FullscreenFilter(true))
)
If this is not the case - for some reason, then I need a minimal sample to take a look into it.
Then, you can either have you Page handle the layout-logic, to decide based on it's width/height how it's layouting. Or probably simpler: You can refresh the page, when the width/height changes, and return a different Node based on the width/height .
@FlorianKirmaier Hi! there is a technical problem with .filter(Filters.FullscreenFilter(true))
.
Initial app when load first time in portrait view!
When switch to Landscape view (by rotating Android device), all is working well:
But when again switch to portrait view, something wrong happens, like zoom out of app:
In the same why when again switch to landscape view, vertical scroll happens:
As see in screen shots something unexpected happens.
Sample code to demonstrate the issue:
package com.jpro.hellojpro;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
import one.jpro.routing.*;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Map;
import static one.jpro.routing.RouteUtils.*;
public class JProScreenOrientationTest extends RouteApp {
private Stage pStage;
@Override
public void start(Stage pStage) {
this.pStage = pStage;
super.start(pStage);
}
@Override
public Route createRoute() {
return Route.empty()
.and(redirect("/", "/info"))
.and(get("/info", (r) -> new InfoPage(pStage)))
.filter(Filters.FullscreenFilter(true));
}
}
class InfoPage extends View {
private Stage pStage;
public InfoPage(Stage pStage) {
this.pStage = pStage;
}
@Override
public String title() {
return "Sample JPro Page";
}
@Override
public String description() {
return "This is a simple page where JPro testing done.";
}
@Override
public Node content() {
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
Label lblText = new Label("+92 (302) 050-6910");
LinkUtil.setLink(lblText, "tel:+923020506910");
Label lblText1 = new Label("cto.ms@outlook.com");
LinkUtil.setLink(lblText1, "mailto:cto.ms@outlook.com");
Label lblText2 = new Label("Info with Parm");
LinkUtil.setLink(lblText2, "/info?q=About");
root.getChildren().addAll(lblText, lblText1, lblText2);
return root;
}
}
defaultpage if it matter somehow:
<!DOCTYPE html>
<html lang="en">
<head>
<title>JPro Testing</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta charset="UTF-8">
<meta name="jpro Application: Hellodescription" content="description"/>
<meta name="description" content="temp">
<link rel="stylesheet" type="text/css" href="/jpro/css/jpro.css">
<script src="/jpro/js/jpro.js" type="text/javascript"></script>
<style>
body {
overflow-x: hidden; /* Hide horizontal scrollbar */
}
</style>
</head>
<div>
<jpro-app href="/app/default" fxContextMenu="false" fullscreen="true" nativeScrolling="true" snapshot="auto" userSelect="true"></jpro-app>
</div>
</body>
</html>
A small tip before looking into the topic in detail:
There is now the method RouteUtils.viewFromNode
, which creates a simple View from a Node. If you don't want to set the description/title/fullscreen, using this method makes the code much more concise.
Hello @ctoabidmaqbool,
The following website shpresa.shop is also running with JPro server. Can you please open it and see if you experience the same issue for some reason? You feedback will help us better understand the issue. Thank You.
@besidev I have tried your provided website. It looks like it's working fine on Desktop Chrome and Android Chrome. e.g. Screen Orientation is working fine.
In both cases Landscape and Portrait responsive forms are fine.
More over this website opensources project or some closed one. It's looks like are forms are made up of using simple html,css,js running on jpro.one server?
I think, WebAPI.getWebAPI(stage).getBrowserSize().getWidth()
or WebAPI.getWebAPI(stage).getBrowserSize().getHeight()
return the correct page width and height. But change listener can't be applied to it, as this not a property rather it's simple values.
System.out.println("browser width: " + WebAPI.getWebAPI(model.getStage()).getBrowserSize().getWidth());
System.out.println("stage width" + model.getStage().getWidth());
System.out.println("browser height: " + WebAPI.getWebAPI(model.getStage()).getBrowserSize().getHeight());
System.out.println("stage height" + model.getStage().getHeight());
stage.getWidth() or stage.getHeight() not return correct page height / width (visible viewport size).
@besidev I have tried your provided website. It looks like it's working fine on Desktop Chrome and Android Chrome. e.g. Screen Orientation is working fine.
In both cases Landscape and Portrait responsive forms are fine.
More over this website opensources project or some closed one. It's looks like are forms are made up of using simple html,css,js running on jpro.one server?
The shpresa.shop website is not open source, but everything is done in JavaFX code, running via JPro server.
I think,
WebAPI.getWebAPI(stage).getBrowserSize().getWidth()
orWebAPI.getWebAPI(stage).getBrowserSize().getHeight()
return the correct page width and height. But change listener can't be applied to it, as this not a property rather it's simple values.System.out.println("browser width: " + WebAPI.getWebAPI(model.getStage()).getBrowserSize().getWidth()); System.out.println("stage width" + model.getStage().getWidth()); System.out.println("browser height: " + WebAPI.getWebAPI(model.getStage()).getBrowserSize().getHeight()); System.out.println("stage height" + model.getStage().getHeight());
stage.getWidth() or stage.getHeight() not return correct page height / width (visible viewport size).
WebAPI.layoutRoot(stage)
is used internally to match the browser's size (width and height) with the root node (container), so basically you should not need to use WebAPI.getWebAPI(stage).getBrowserSize().getWidth()
and WebAPI.getWebAPI(stage).getBrowserSize().getHeight()
or even the property if it was in the WebAPI, the width/height property of the root container should hold the correct values you need. We need to investigate this part.
Yes! As Javafx -> CSS doesn't have media queries yet. It's must be possible to get correct width and height of page to emulate media queries using javafx!
Okey! Still we can't get height of root element by using this method e.g. root.getHeight()
however root.getWidth()
somehow works.
Hi! After a couple of try, researching and tying provided fixes, I have got expected behavior!
ResponsiveApp.java
package com.jpro.hellojpro;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import one.jpro.routing.Filters;
import one.jpro.routing.Route;
import one.jpro.routing.RouteApp;
import one.jpro.routing.RouteUtils;
public class ResponsiveApp extends RouteApp {
Label infoWidth;
Label infoHeight;
public static void main(String[] args) {
launch(args);
}
public Route createRoute() {
return Route.empty()
.and(RouteUtils.getNode("/", (r) -> getView()))
.filter(Filters.FullscreenFilter(true));
// .filter(DevFilter.create());
}
private Node getView() {
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
infoWidth = new Label("Width");
infoHeight = new Label("Height");
Label infoOrientation = new Label("Orientation");
Label infoDisplay = new Label("Display");
root.getChildren().addAll(infoWidth, infoHeight, infoOrientation, infoDisplay);
Scene scene = getScene();
runOnOrientationChanged(scene, () -> {
infoOrientation.setText("Orientaion: Landscape");
}, () -> {
infoOrientation.setText("Orientaion: Portrait");
});
runOnWidthChanged(scene, () -> {
infoDisplay.setText("Display: Laptop");
}, () -> {
infoDisplay.setText("Display: Tablet");
}, () -> {
infoDisplay.setText("Display: Android");
});
return root;
}
public void runOnOrientationChanged(Scene scene, Runnable runOnLandscape, Runnable runOnPortrait) {
BooleanProperty orientationProperty = new SimpleBooleanProperty();
scene.widthProperty().addListener((observable, oldValue, newValue) -> {
infoWidth.setText("Width: " + newValue);
orientationProperty.set(newValue.doubleValue() > scene.getHeight());
});
scene.heightProperty().addListener((observable, oldValue, newValue) -> {
infoHeight.setText("Height: " + newValue);
orientationProperty.set(newValue.doubleValue() < scene.getWidth());
});
orientationProperty.addListener((observable, oldValue, newValue) -> {
if (newValue) {
runOnLandscape.run();
} else {
runOnPortrait.run();
}
});
// First run even if Stage width not changed
if (scene.getWidth() > scene.getHeight()) {
// System.out.println("Landscape Display");
runOnLandscape.run();
} else {
// System.out.println("Portrait Display");
runOnPortrait.run();
}
}
public void runOnWidthChanged(Scene scene, Runnable runOnG800, Runnable runOnL800, Runnable runOnL380) {
BooleanProperty widthG800 = new SimpleBooleanProperty();
BooleanProperty widthL380 = new SimpleBooleanProperty();
scene.widthProperty().addListener((observable, oldValue, newValue) -> {
widthG800.set((newValue.intValue() > 800));
widthL380.set((newValue.intValue() < 380));
});
widthG800.addListener((observable, oldValue, newValue) -> {
if (newValue) { // > 800
// System.out.println("Laptop Display");
runOnG800.run();
} else { // <= 800
// System.out.println("Tablet Display");
runOnL800.run();
}
});
widthL380.addListener((observable, oldValue, newValue) -> {
if (newValue) { // < 380
// System.out.println("Android Display");
runOnL380.run();
} else { // >= 380
// System.out.println("Tablet Display");
runOnL800.run();
}
});
// First run even if Stage width not changed
if (scene.getWidth() > 800) {
// System.out.println("Laptop Display");
runOnG800.run();
} else if (scene.getWidth() >= 380) {
// System.out.println("Tablet Display");
runOnL800.run();
} else {
// System.out.println("Android Display");
runOnL380.run();
}
}
}
defaultpage
<!DOCTYPE html>
<html lang="en">
<head>
<title>JPro Responsive Testing</title>
<meta name="description" content="An application for testing of Responsive in jPro">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="/jpro/css/jpro.css">
<script src="/jpro/js/jpro.js" type="text/javascript"></script>
<style>
body {
overflow-x: hidden;
}
</style>
</head>
<body>
<div>
<jpro-app href="/app/default" fxContextMenu="false" fullscreen="true" loader="none" nativeScrolling="true"
snapshot="auto" userSelect="true" fxHeight="false" />
</div>
</body>
</html>
@FlorianKirmaier @besidev ! Please see my above code, it's almost working fine.
But there is some problem. It's looks like <meta name="viewport" content="width=device-width, initial-scale=1.0">
not working. e.g. when you resize page in chrome-inspect view
page scales too & fro.
How to fix it, in a case all other codding should works too?
But there is some problem. It's looks like not working. e.g. when you resize page in chrome-inspect view page scales too & fro.
Can you explain more about what you mean? When I use the dev console and select a predefined screen size, and zoom, nothing happens. But that's the case for all web pages I've tested, independent of JPro. What is the behavior you get, and what would you expect?
@FlorianKirmaier I am talking about simple.
Let open https://google.com website in chrome, and resize the page (the scaling of the page will not be changed, or zoom in/out remains same):
Now open jpro app (above code), and resize the page:
On resizing the page the scaling of page will be changed, or zoom in/out will be changed on resizing, e.g.:
Let me know, if still you not get-up the error or issue?
Hi! I have an JPro App running on my local pc. I am trying to connect my App on Android device using local network, e.g. through IP address.
When orientation of device changes sometime codding not works correctly!
Basically we are using listener on stage which compare width and height to calculate orientation of device e.g. Portrait or Landscape.
We are using latest release of JPro plugin (except routing).
We have implemented something like this method for detection of screen orientation.