添加最小化和还原动画 (#3657)
* update * update * update * update * update * update * update * update * update * fix checkstyle
This commit is contained in:
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.ui;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXButton;
|
import com.jfoenix.controls.JFXButton;
|
||||||
import com.jfoenix.controls.JFXDialogLayout;
|
import com.jfoenix.controls.JFXDialogLayout;
|
||||||
import javafx.animation.Interpolator;
|
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
import javafx.animation.KeyValue;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
@@ -50,7 +49,6 @@ import org.jackhuang.hmcl.ui.account.AccountListPage;
|
|||||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
import org.jackhuang.hmcl.ui.decorator.Decorator;
|
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
import org.jackhuang.hmcl.ui.decorator.DecoratorController;
|
||||||
import org.jackhuang.hmcl.ui.download.DownloadPage;
|
import org.jackhuang.hmcl.ui.download.DownloadPage;
|
||||||
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
|
||||||
@@ -274,19 +272,19 @@ public final class Controllers {
|
|||||||
stage.initStyle(StageStyle.TRANSPARENT);
|
stage.initStyle(StageStyle.TRANSPARENT);
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
|
|
||||||
if (AnimationUtils.isAnimationEnabled() && !OperatingSystem.CURRENT_OS.isLinuxOrBSD()) {
|
if (AnimationUtils.playWindowAnimation()) {
|
||||||
Decorator node = decorator.getDecorator();
|
|
||||||
Interpolator ease = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
|
||||||
Timeline timeline = new Timeline(
|
Timeline timeline = new Timeline(
|
||||||
new KeyFrame(Duration.millis(0),
|
new KeyFrame(Duration.millis(0),
|
||||||
new KeyValue(node.opacityProperty(), 0, ease),
|
new KeyValue(decorator.getDecorator().opacityProperty(), 0, FXUtils.EASE),
|
||||||
new KeyValue(node.scaleXProperty(), 0.3, ease),
|
new KeyValue(decorator.getDecorator().scaleXProperty(), 0.8, FXUtils.EASE),
|
||||||
new KeyValue(node.scaleYProperty(), 0.3, ease)
|
new KeyValue(decorator.getDecorator().scaleYProperty(), 0.8, FXUtils.EASE),
|
||||||
|
new KeyValue(decorator.getDecorator().scaleZProperty(), 0.8, FXUtils.EASE)
|
||||||
),
|
),
|
||||||
new KeyFrame(Duration.millis(800),
|
new KeyFrame(Duration.millis(600),
|
||||||
new KeyValue(node.opacityProperty(), 1, ease),
|
new KeyValue(decorator.getDecorator().opacityProperty(), 1, FXUtils.EASE),
|
||||||
new KeyValue(node.scaleXProperty(), 1, ease),
|
new KeyValue(decorator.getDecorator().scaleXProperty(), 1, FXUtils.EASE),
|
||||||
new KeyValue(node.scaleYProperty(), 1, ease)
|
new KeyValue(decorator.getDecorator().scaleYProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(decorator.getDecorator().scaleZProperty(), 1, FXUtils.EASE)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
timeline.play();
|
timeline.play();
|
||||||
|
|||||||
@@ -1085,6 +1085,8 @@ public final class FXUtils {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final Interpolator EASE = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||||
|
|
||||||
public static void onEscPressed(Node node, Runnable action) {
|
public static void onEscPressed(Node node, Runnable action) {
|
||||||
node.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
|
node.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
|
||||||
if (e.getCode() == KeyCode.ESCAPE) {
|
if (e.getCode() == KeyCode.ESCAPE) {
|
||||||
|
|||||||
@@ -1,7 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
package org.jackhuang.hmcl.ui.animation;
|
package org.jackhuang.hmcl.ui.animation;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.setting.ConfigHolder;
|
import org.jackhuang.hmcl.setting.ConfigHolder;
|
||||||
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Glavo
|
||||||
|
*/
|
||||||
public final class AnimationUtils {
|
public final class AnimationUtils {
|
||||||
|
|
||||||
private AnimationUtils() {
|
private AnimationUtils() {
|
||||||
@@ -20,4 +41,8 @@ public final class AnimationUtils {
|
|||||||
public static boolean isAnimationEnabled() {
|
public static boolean isAnimationEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean playWindowAnimation() {
|
||||||
|
return isAnimationEnabled() && !OperatingSystem.CURRENT_OS.isLinuxOrBSD();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
package org.jackhuang.hmcl.ui.decorator;
|
package org.jackhuang.hmcl.ui.decorator;
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXSnackbar;
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.KeyValue;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
@@ -35,6 +38,9 @@ import javafx.scene.layout.StackPane;
|
|||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.StageStyle;
|
import javafx.stage.StageStyle;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||||
import org.jackhuang.hmcl.ui.wizard.Navigation;
|
import org.jackhuang.hmcl.ui.wizard.Navigation;
|
||||||
|
|
||||||
public class Decorator extends Control {
|
public class Decorator extends Control {
|
||||||
@@ -61,12 +67,40 @@ public class Decorator extends Control {
|
|||||||
private final ReadOnlyBooleanWrapper allowMove = new ReadOnlyBooleanWrapper();
|
private final ReadOnlyBooleanWrapper allowMove = new ReadOnlyBooleanWrapper();
|
||||||
private final ReadOnlyBooleanWrapper dragging = new ReadOnlyBooleanWrapper();
|
private final ReadOnlyBooleanWrapper dragging = new ReadOnlyBooleanWrapper();
|
||||||
|
|
||||||
|
private boolean playRestoreMinimizeAnimation = false;
|
||||||
|
|
||||||
public Decorator(Stage primaryStage) {
|
public Decorator(Stage primaryStage) {
|
||||||
this.primaryStage = primaryStage;
|
this.primaryStage = primaryStage;
|
||||||
|
|
||||||
setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
|
setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||||
|
|
||||||
primaryStage.initStyle(StageStyle.UNDECORATED);
|
primaryStage.initStyle(StageStyle.UNDECORATED);
|
||||||
|
|
||||||
|
if (AnimationUtils.playWindowAnimation()) {
|
||||||
|
FXUtils.onChange(primaryStage.iconifiedProperty(), iconified -> {
|
||||||
|
if (playRestoreMinimizeAnimation && !iconified) {
|
||||||
|
playRestoreMinimizeAnimation = false;
|
||||||
|
Timeline timeline = new Timeline(
|
||||||
|
new KeyFrame(Duration.millis(0),
|
||||||
|
new KeyValue(this.opacityProperty(), 0, FXUtils.EASE),
|
||||||
|
new KeyValue(this.translateYProperty(), 200, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleXProperty(), 0.4, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleYProperty(), 0.4, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleZProperty(), 0.4, FXUtils.EASE)
|
||||||
|
),
|
||||||
|
new KeyFrame(Duration.millis(200),
|
||||||
|
new KeyValue(this.opacityProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.translateYProperty(), 0, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleXProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleYProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleZProperty(), 1, FXUtils.EASE)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
timeline.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stage getPrimaryStage() {
|
public Stage getPrimaryStage() {
|
||||||
@@ -239,8 +273,30 @@ public class Decorator extends Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void minimize() {
|
public void minimize() {
|
||||||
|
if (AnimationUtils.playWindowAnimation()) {
|
||||||
|
playRestoreMinimizeAnimation = true;
|
||||||
|
Timeline timeline = new Timeline(
|
||||||
|
new KeyFrame(Duration.millis(0),
|
||||||
|
new KeyValue(this.opacityProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.translateYProperty(), 0, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleXProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleYProperty(), 1, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleZProperty(), 1, FXUtils.EASE)
|
||||||
|
),
|
||||||
|
new KeyFrame(Duration.millis(200),
|
||||||
|
new KeyValue(this.opacityProperty(), 0, FXUtils.EASE),
|
||||||
|
new KeyValue(this.translateYProperty(), 200, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleXProperty(), 0.4, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleYProperty(), 0.4, FXUtils.EASE),
|
||||||
|
new KeyValue(this.scaleZProperty(), 0.4, FXUtils.EASE)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
timeline.setOnFinished(event -> primaryStage.setIconified(true));
|
||||||
|
timeline.play();
|
||||||
|
} else {
|
||||||
primaryStage.setIconified(true);
|
primaryStage.setIconified(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
onCloseButtonAction.get().run();
|
onCloseButtonAction.get().run();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.ui.decorator;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXDialog;
|
import com.jfoenix.controls.JFXDialog;
|
||||||
import com.jfoenix.controls.JFXSnackbar;
|
import com.jfoenix.controls.JFXSnackbar;
|
||||||
import javafx.animation.Interpolator;
|
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
import javafx.animation.KeyValue;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
@@ -55,7 +54,6 @@ import org.jackhuang.hmcl.ui.construct.Navigator;
|
|||||||
import org.jackhuang.hmcl.ui.construct.StackContainerPane;
|
import org.jackhuang.hmcl.ui.construct.StackContainerPane;
|
||||||
import org.jackhuang.hmcl.ui.wizard.Refreshable;
|
import org.jackhuang.hmcl.ui.wizard.Refreshable;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -89,25 +87,21 @@ public class DecoratorController {
|
|||||||
public DecoratorController(Stage stage, Node mainPage) {
|
public DecoratorController(Stage stage, Node mainPage) {
|
||||||
decorator = new Decorator(stage);
|
decorator = new Decorator(stage);
|
||||||
decorator.setOnCloseButtonAction(() -> {
|
decorator.setOnCloseButtonAction(() -> {
|
||||||
if (AnimationUtils.isAnimationEnabled() && !OperatingSystem.CURRENT_OS.isLinuxOrBSD()) {
|
if (AnimationUtils.playWindowAnimation()) {
|
||||||
Interpolator ease = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
Timeline timeline = new Timeline(
|
||||||
|
|
||||||
Timeline timeline = (new Timeline(
|
|
||||||
new KeyFrame(Duration.millis(0),
|
new KeyFrame(Duration.millis(0),
|
||||||
new KeyValue(decorator.opacityProperty(), 1, ease),
|
new KeyValue(decorator.opacityProperty(), 1, FXUtils.EASE),
|
||||||
new KeyValue(decorator.translateYProperty(), 0, ease),
|
new KeyValue(decorator.scaleXProperty(), 1, FXUtils.EASE),
|
||||||
new KeyValue(decorator.scaleXProperty(), 1, ease),
|
new KeyValue(decorator.scaleYProperty(), 1, FXUtils.EASE),
|
||||||
new KeyValue(decorator.scaleYProperty(), 1, ease),
|
new KeyValue(decorator.scaleZProperty(), 0.3, FXUtils.EASE)
|
||||||
new KeyValue(decorator.scaleZProperty(), 0.3, ease)
|
|
||||||
),
|
),
|
||||||
new KeyFrame(Duration.millis(400),
|
new KeyFrame(Duration.millis(200),
|
||||||
new KeyValue(decorator.opacityProperty(), 0, ease),
|
new KeyValue(decorator.opacityProperty(), 0, FXUtils.EASE),
|
||||||
new KeyValue(decorator.translateYProperty(), 200, ease),
|
new KeyValue(decorator.scaleXProperty(), 0.8, FXUtils.EASE),
|
||||||
new KeyValue(decorator.scaleXProperty(), 0.3, ease),
|
new KeyValue(decorator.scaleYProperty(), 0.8, FXUtils.EASE),
|
||||||
new KeyValue(decorator.scaleYProperty(), 0.3, ease),
|
new KeyValue(decorator.scaleZProperty(), 0.8, FXUtils.EASE)
|
||||||
new KeyValue(decorator.scaleZProperty(), 0.3, ease)
|
|
||||||
)
|
)
|
||||||
));
|
);
|
||||||
timeline.setOnFinished(event -> Launcher.stopApplication());
|
timeline.setOnFinished(event -> Launcher.stopApplication());
|
||||||
timeline.play();
|
timeline.play();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user