feat: title bar swipe animation.

This commit is contained in:
Yuhui Huang 2021-08-02 16:46:45 +08:00
parent 5da4ad7a62
commit 0939ed819e
6 changed files with 84 additions and 10 deletions

View File

@ -173,7 +173,49 @@ public enum ContainerAnimations {
new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH)),
new KeyFrame(c.getDuration(),
new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH))));
new KeyValue(c.getPreviousNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))),
SWIPE_LEFT_FADE_SHORT(c -> {
c.getPreviousNode().setScaleX(1);
c.getPreviousNode().setScaleY(1);
c.getPreviousNode().setOpacity(0);
c.getPreviousNode().setTranslateX(0);
c.getCurrentNode().setScaleX(1);
c.getCurrentNode().setScaleY(1);
c.getCurrentNode().setOpacity(1);
c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth());
}, c ->
Arrays.asList(new KeyFrame(Duration.ZERO,
new KeyValue(c.getCurrentNode().translateXProperty(), 50, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getCurrentNode().opacityProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().opacityProperty(), 1, Interpolator.EASE_BOTH)),
new KeyFrame(c.getDuration(),
new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().translateXProperty(), -50, Interpolator.EASE_BOTH),
new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH)))),
SWIPE_RIGHT_FADE_SHORT(c -> {
c.getPreviousNode().setScaleX(1);
c.getPreviousNode().setScaleY(1);
c.getPreviousNode().setOpacity(0);
c.getPreviousNode().setTranslateX(0);
c.getCurrentNode().setScaleX(1);
c.getCurrentNode().setScaleY(1);
c.getCurrentNode().setOpacity(1);
c.getCurrentNode().setTranslateX(c.getCurrentRoot().getWidth());
}, c ->
Arrays.asList(new KeyFrame(Duration.ZERO,
new KeyValue(c.getCurrentNode().translateXProperty(), -50, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getCurrentNode().opacityProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().opacityProperty(), 1, Interpolator.EASE_BOTH)),
new KeyFrame(c.getDuration(),
new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().translateXProperty(), 50, Interpolator.EASE_BOTH),
new KeyValue(c.getCurrentNode().opacityProperty(), 1, Interpolator.EASE_BOTH),
new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))));
private final AnimationProducer animationProducer;
private ContainerAnimations opposite;

View File

@ -30,6 +30,7 @@ import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.animation.AnimationProducer;
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.animation.TransitionPane;
import org.jackhuang.hmcl.ui.wizard.Navigation;
import org.jackhuang.hmcl.util.Logging;
import java.util.Optional;
@ -48,7 +49,7 @@ public class Navigator extends TransitionPane {
backable.set(canGoBack());
getChildren().setAll(init);
fireEvent(new NavigationEvent(this, init, NavigationEvent.NAVIGATED));
fireEvent(new NavigationEvent(this, init, Navigation.NavigationDirection.START, NavigationEvent.NAVIGATED));
initialized = true;
}
@ -68,14 +69,14 @@ public class Navigator extends TransitionPane {
stack.push(node);
backable.set(canGoBack());
NavigationEvent navigating = new NavigationEvent(this, from, NavigationEvent.NAVIGATING);
NavigationEvent navigating = new NavigationEvent(this, from, Navigation.NavigationDirection.NEXT, NavigationEvent.NAVIGATING);
fireEvent(navigating);
node.fireEvent(navigating);
node.getProperties().put("hmcl.navigator.animation", animationProducer);
setContent(node, animationProducer);
NavigationEvent navigated = new NavigationEvent(this, node, NavigationEvent.NAVIGATED);
NavigationEvent navigated = new NavigationEvent(this, node, Navigation.NavigationDirection.NEXT, NavigationEvent.NAVIGATED);
node.fireEvent(navigated);
EventHandler<PageCloseEvent> handler = event -> close(node);
@ -111,7 +112,7 @@ public class Navigator extends TransitionPane {
backable.set(canGoBack());
Node node = stack.peek();
NavigationEvent navigating = new NavigationEvent(this, from, NavigationEvent.NAVIGATING);
NavigationEvent navigating = new NavigationEvent(this, from, Navigation.NavigationDirection.PREVIOUS, NavigationEvent.NAVIGATING);
fireEvent(navigating);
node.fireEvent(navigating);
@ -122,7 +123,7 @@ public class Navigator extends TransitionPane {
setContent(node, ContainerAnimations.NONE.getAnimationProducer());
}
NavigationEvent navigated = new NavigationEvent(this, node, NavigationEvent.NAVIGATED);
NavigationEvent navigated = new NavigationEvent(this, node, Navigation.NavigationDirection.PREVIOUS, NavigationEvent.NAVIGATED);
node.fireEvent(navigated);
Optional.ofNullable(from.getProperties().get(PROPERTY_DIALOG_CLOSE_HANDLER))
@ -206,12 +207,14 @@ public class Navigator extends TransitionPane {
private final Navigator source;
private final Node node;
private final Navigation.NavigationDirection direction;
public NavigationEvent(Navigator source, Node target, EventType<? extends Event> eventType) {
public NavigationEvent(Navigator source, Node target, Navigation.NavigationDirection direction, EventType<? extends Event> eventType) {
super(source, target, eventType);
this.source = source;
this.node = target;
this.direction = direction;
}
@Override
@ -222,5 +225,9 @@ public class Navigator extends TransitionPane {
public Node getNode() {
return node;
}
public Navigation.NavigationDirection getDirection() {
return direction;
}
}
}

View File

@ -34,6 +34,7 @@ import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.jackhuang.hmcl.ui.wizard.Navigation;
public class Decorator extends Control {
private final ListProperty<Node> drawer = new SimpleListProperty<>(FXCollections.observableArrayList());
@ -51,6 +52,7 @@ public class Decorator extends Control {
private final BooleanProperty canClose = new SimpleBooleanProperty(false);
private final BooleanProperty showCloseAsHome = new SimpleBooleanProperty(false);
private final Stage primaryStage;
private Navigation.NavigationDirection navigationDirection = Navigation.NavigationDirection.START;
private StackPane drawerWrapper;
private final ReadOnlyBooleanWrapper allowMove = new ReadOnlyBooleanWrapper();
@ -238,4 +240,13 @@ public class Decorator extends Control {
e.consume();
});
}
// TODO: Dirty implementation.
public Navigation.NavigationDirection getNavigationDirection() {
return navigationDirection;
}
public void setNavigationDirection(Navigation.NavigationDirection navigationDirection) {
this.navigationDirection = navigationDirection;
}
}

View File

@ -243,6 +243,8 @@ public class DecoratorController {
decorator.showCloseAsHomeProperty().set(true);
}
decorator.setNavigationDirection(event.getDirection());
// state property should be updated at last.
if (to instanceof DecoratorPage) {
decorator.stateProperty().bind(((DecoratorPage) to).stateProperty());

View File

@ -41,8 +41,10 @@ import javafx.util.Duration;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.animation.AnimationProducer;
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.animation.TransitionPane;
import org.jackhuang.hmcl.ui.wizard.Navigation;
import org.jackhuang.hmcl.util.Lang;
public class DecoratorSkin extends SkinBase<Decorator> {
@ -165,7 +167,16 @@ public class DecoratorSkin extends SkinBase<Decorator> {
Node node = createNavBar(skinnable, s.isTitleBarTransparent(), s.getLeftPaneWidth(), s.isBackable(), skinnable.canCloseProperty().get(), skinnable.showCloseAsHomeProperty().get(), s.isRefreshable(), s.getTitle(), s.getTitleNode());
double targetOpacity = s.isTitleBarTransparent() ? 0 : 1;
if (s.isAnimate()) {
navBarPane.setContent(node, ContainerAnimations.FADE.getAnimationProducer());
AnimationProducer animation;
if (skinnable.getNavigationDirection() == Navigation.NavigationDirection.NEXT) {
animation = ContainerAnimations.SWIPE_LEFT_FADE_SHORT.getAnimationProducer();
} else if (skinnable.getNavigationDirection() == Navigation.NavigationDirection.PREVIOUS) {
animation = ContainerAnimations.SWIPE_RIGHT_FADE_SHORT.getAnimationProducer();
} else {
animation = ContainerAnimations.FADE.getAnimationProducer();
}
skinnable.setNavigationDirection(Navigation.NavigationDirection.START);
navBarPane.setContent(node, animation);
} else {
navBarPane.getChildren().setAll(node);
}

View File

@ -26,6 +26,7 @@ import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.construct.Navigator;
import org.jackhuang.hmcl.ui.construct.TabControl;
import org.jackhuang.hmcl.ui.construct.TabHeader;
import org.jackhuang.hmcl.ui.wizard.Navigation;
public abstract class DecoratorTabPage extends DecoratorTransitionPage implements TabControl {
@ -36,10 +37,10 @@ public abstract class DecoratorTabPage extends DecoratorTransitionPage implement
}
if (newValue.getNode() != null) {
onNavigating(getCurrentPage());
if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigator.NavigationEvent.NAVIGATING));
if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigation.NavigationDirection.NEXT, Navigator.NavigationEvent.NAVIGATING));
navigate(newValue.getNode(), ContainerAnimations.FADE.getAnimationProducer());
onNavigated(getCurrentPage());
if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigator.NavigationEvent.NAVIGATED));
if (getCurrentPage() != null) getCurrentPage().fireEvent(new Navigator.NavigationEvent(null, getCurrentPage(), Navigation.NavigationDirection.NEXT, Navigator.NavigationEvent.NAVIGATED));
}
});
}