在開發視窗軟體時幾乎都會遇到一個問題:放大縮小跑版
要因應各種不同的解析度/螢幕比例,最好的方式就是根據不同螢幕去做最佳化,但是這是一種幾乎做不完的工程,於是我在開發程式時的思路就是將UI都比照影片的方式辦理,進行全畫面的等比放大/縮小,既能節省開發時間,也能減少跑版問題。
1.Fxml檔的root元件依照以下方式排列與設定屬性:
root使用GridPane,並且裡面放一個AnchorPane比較好設計畫面。
GridPane依照以下屬性設定:
然後AnchorPane也設定成以下屬性:
說明:
1.GridPane的背景顏色為APP的底色
2.GridPane跟AnchorPane的Pref Widtth跟Pref Height
需要一個基本解析度做開發,如果螢幕小於這個解析度,還是會遇到顯示問題(畫面超出螢幕範圍),所以這邊須配合軟體系統需求做規劃。
這兩個元件的解析度需要設成一樣,才能同步縮放。
2.程式碼加入相對應處理:
由程式碼去監控畫面尺寸變化,並做比例縮放的動作
private MainActivityController mMainActivityController; @Override public void start(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("fxml/activity_main.fxml")); Pane root = fxmlLoader.load(); stage.setTitle("World"); Scene scene = new Scene(root); stage.setScene(scene); stage.setMinWidth(800); stage.setMinHeight(600); stage.show(); mMainActivityController = fxmlLoader.getController(); //畫面縮放功能 letterbox(scene, root); } private void letterbox(final Scene scene, final Pane contentPane) { final double initWidth = scene.getWidth(); final double initHeight = scene.getHeight(); final double ratio = initWidth / initHeight; SceneSizeChangeListener sizeListener = new SceneSizeChangeListener(scene, ratio, initHeight, initWidth, contentPane); scene.widthProperty().addListener(sizeListener); scene.heightProperty().addListener(sizeListener); } private record SceneSizeChangeListener(Scene scene, double ratio, double initHeight, double initWidth, Pane contentPane) implements ChangeListener<Number> { @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) { final double newWidth = scene.getWidth(); final double newHeight = scene.getHeight(); double scaleFactor = newWidth / newHeight > ratio ? newHeight / initHeight : newWidth / initWidth; //如須能縮小,則設為0(或一個最小的倍數) if (scaleFactor >= 1) { Scale scale = new Scale(scaleFactor, scaleFactor); //如需要中心放大,則使用(newWidth/2),(newHeight/2),測試用的root元件為GridPane,Alignment設為TOP_LEFT,第二層為AnchorPane,V/Halignment設為CENTER scale.setPivotX(newWidth / 2); scale.setPivotY(newHeight / 2); scene.getRoot().getTransforms().setAll(scale); contentPane.setPrefWidth(newWidth / scaleFactor); contentPane.setPrefHeight(newHeight / scaleFactor); } else { contentPane.setPrefWidth(Math.max(initWidth, newWidth)); contentPane.setPrefHeight(Math.max(initHeight, newHeight)); } } }
這樣就能自由等比放大~全螢幕了
-END-
發佈留言